nebulab / erb-formatter

Format ERB files with speed and precision
MIT License
135 stars 22 forks source link

Formatter is too slow #28

Open vfonic opened 1 year ago

vfonic commented 1 year ago

I installed the VS Code extension[1] after seeing this in the README here:

Features:

  • very fast

It takes ~1.7 seconds to format a single 33 lines of code ERB file on save.

VS Code extension output logs ``` executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 2s 464ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 716ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 946ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 745ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 803ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 710ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 771ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 767ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 763ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 701ms executing: /Users//.rvm/gems/ruby-3.2.2/bin/erb-format --stdin-filename "/Users//Developer/jsp/app/views/devise/sessions/new.html.erb" --print-width 80 completed in 1s 681ms ```

Am I doing something wrong? Can this be made faster?

[1] https://marketplace.visualstudio.com/items?itemName=elia.erb-formatter

elia commented 10 months ago

@vfonic I'd be very interested in what kind of code is in those 33 lines, so far my experience was very different but if there's some sort of edge case in which performance plummet I would be interested in solving them

vfonic commented 10 months ago

I don't think it's code related.

Here's the code:

<% content_for :form_block do %>
  <div class="mb-4 text-center">
    <h2 class="mb-px"><%= t('.sign_in') %></h2>
    <%= t ".sign_up_html", link: link_to("sign up for an account", new_registration_path(resource_name), class: "font-semibold") if registrations_enabled? %>
  </div>

  <%= form_with(model: resource, as: resource_name, url: session_path(resource_name)) do |f| %>
    <div class="form-group">
      <%= f.label :email %>
      <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: true, class: "form-control" %>
    </div>

    <div class="form-group">
      <%= f.label :password %>
      <%= f.password_field :password, autocomplete: "current-password", placeholder: true, class: "form-control" %>
    </div>

    <% if devise_mapping.rememberable? -%>
      <div class="form-group">
        <%= f.check_box :remember_me, class: "form-checkbox" %>
        <%= f.label :remember_me, class: "inline-block" %>
      </div>
    <% end -%>

    <div class="form-group">
      <%= f.submit t('.sign_in'), class: "btn btn-primary btn-expanded" %>
    </div>
  <% end %>

  <%= render "devise/shared/links" %>
<% end %>

<%= render "devise/shared/form_block" %>
elia commented 9 months ago

@vfonic looks like it's fast on my machine, which means it could be related to what box you're running it on to, so if you want to give me some specs I can try to reword that line in the readme so to add the proper context.


For the record here are my results in VSC (on an Apple M1 laptop):

image

While running it directly in the terminal takes from 12 to 16 microseconds.

vfonic commented 9 months ago

I also have M1.

I reinstalled Homebrew (from Rosetta to ARM), reinstalled RVM, basically most of my setup.

Now the formatting is done in 400-500ms.

I still find that just slow enough that say it's "very fast" is misleading.

Here's a screen recording of my RuboCop formatting setup speed vs erb-formatter formatting speed. Please note that in this project RuboCop has a huge config to load (consisting of many included configs and some custom cops), and it overall does much more than erb-formatter. RuboCop seems to be doing the formatting in <100ms. It feels instant:

https://github.com/nebulab/erb-formatter/assets/67437/32145d14-ca6a-4211-8b75-a63a27d0da6a

elia commented 6 months ago

@vfonic Thanks for the heads up, this is a very valid point, I think the main difference is that the rubocop extension is using a server process + caching instead of individual runs.

Running the formatter against 61 files took about 10ms per file on my machine:

solidus:main * ⤑ time bundle exec erb-format --tailwind-output-path admin/app/assets/builds/solidus_admin/tailwind.css --print-width 120 -w admin/**/*.html.erb                                        ~/C/N/solidus

________________________________________________________
Executed in  753.92 millis    fish           external
   usr time  449.28 millis   94.00 micros  449.18 millis
   sys time  144.58 millis  531.00 micros  144.05 millis

solidus:main * ⤑ irb                                                                                                                                                                                   ~/C/N/solidus
>> Dir["admin/**/*.html.erb"].count
=> 61
>> 753.92 / 61
=> 12.359344262295082
>> 

So I think that we can try to find a way to use the same trick rubocop uses and be 10x more instant 😅 Jokes aside, could you send a PR with a proposal for a more accurate description in the README? (Or even better to help on the vscode extension!)

vfonic commented 6 months ago

I think the main difference is that the rubocop extension is using a server process + caching instead of individual runs.

Yes, I've set up RuboCop to use rubocop-daemon to run the RuboCop server in the background: https://github.com/fohte/rubocop-daemon

I'm a bit swamped with work at the moment, but if I find some time I'll look into optimizing the extension.

Thanks!