Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid a lot of NameError exceptions #1725

Closed
wants to merge 2 commits into from

Conversation

kriom
Copy link

@kriom kriom commented Jan 28, 2021

Purpose

Greatly improves rendering time by avoiding the generation of NameError exception

Context

Rendering a view with 966 inputs (ok I admit it's a mess) allowed me to see that this portion of code is not optimized at all.

I used https://github.com/tmm1/stackprof on my view to understand via the flamegraph that ~ 70% of the time is dedicated to handle NameError exceptions.

Changes

Instead of trying to obtain a constant directly, it is verified that it exists first.

Results

development environment :

Flamegraph ⬅️ before and after ➡️ fix :
Flamegraph before fix Flamegraph after fix
As you can see before the fix, a lot of time was spent in the SimpleForm::FormBuilder#attempt_maping.

In the development environment the view rendering speed up is ~=> X 5.0

production environment : ( edit: not reproduced afterwards )

The same view goes from :
Completed 200 OK in 2658ms (Views: 2637.2ms | ActiveRecord: 12.0ms | Allocations: 1240207)
to
Completed 200 OK in 1503ms (Views: 1482.9ms | ActiveRecord: 13.3ms | Allocations: 1244907)

In the production environment the view rendering speed up is ~=> (2637 / 1482) = X 1.78

And many thanks for your great work 😙

Hardly improves rendering time by avoiding the generation of NameError exception
Copy link
Member

@carlosantoniodasilva carlosantoniodasilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution, I had a suggestion below to test out if you can.

Are you testing this in production mode? And do you have cache_discovery enabled? Otherwise I think it will try to do the mapping lookups on every request (it should be on by default I think in production)

lib/simple_form/form_builder.rb Outdated Show resolved Hide resolved
Co-authored-by: Carlos Antonio da Silva <[email protected]>
@kriom
Copy link
Author

kriom commented Jan 29, 2021

I tested it in development and production modes but generated flamgraphs come from development mode
Rails log give me these speed up

  • X 5.0 for development
  • X 1.78 for production ( edit: not reproduced afterwards )

I use the default configuration for cache_discovery.
config/initializers/simple_form.rb

...
  # Cache SimpleForm inputs discovery
  # config.cache_discovery = !Rails.env.development?
...

In development cache_discovery is off

[3] pry(main)> Rails.env
=> "development"
[4] pry(main)> SimpleForm.cache_discovery
=> false

In production cache_discovery is on

irb(main):001:0> Rails.env
=> "production"
irb(main):002:0> SimpleForm.cache_discovery 
=> true

I will generate 2 flamegraphs without and with the fix in production mode

@kriom
Copy link
Author

kriom commented Feb 5, 2021

Hello,

In production mode with and without the patch of this PR:

  • the rendering durations are identical,
  • the generated flamgraphs are identical.

I can no longer reproduce my performance improvement in production with only this patch. Which seems logical compared to what you say. It must have been due to another correction of my view (Oops).

So this improvement is only valid for the development mode.

@carlosantoniodasilva
Copy link
Member

Thanks @kriom, I believe that in production that discovery cache option takes place and helps prevent the many NameError rescues you were seeing in development.

I hope to circle back on this for review in the next few days.

@cymen
Copy link

cymen commented May 22, 2021

@carlosantoniodasilva I came across this issue while researching a similar simple_form rendering time issue and I found in our configuration, we had the default generated config that has the discovery cache option (that turns it off in non-development) commented out. Would a PR to change that so the option is not commented out in the configuration file be accepted?

I suspect many people are running simple_form in production with cache_discovery enabled and are not aware. The change I suggest above won't help them but at least new users won't experience that.

I was also surprised that I couldn't find any documentation for the discovery cache configuration setting. Maybe the impact isn't as dramatic in production but when I toggled it on in development, the admittedly complex form we are rendering took a bit less than 50% of the original time to render.

@carlosantoniodasilva
Copy link
Member

Thanks for your work on this one @kriom, and my apologies for not circling back on it back then. We got a similar change in #1810, so I went ahead and merged that, credited both of you in the changelog.

@cymen I'm afraid that enabling that by default could have side-effects with code reloading in dev, i.e. if you make changes to input code it could remove the previous cached constant for example... this is off the top of my head, untested, but sounds like it would be possible. If you would like to give that a try and doesn't run into any issues, we could consider enabling that on by default in dev, but otherwise I think this should be fine as is. We could of course improve documentation on that config. (it should be on by default in production though.)

Thanks all!

@carlosantoniodasilva
Copy link
Member

I'm reverting the merged change, as it caused a regression. See #1824 for more info.

Happy to review something else that fixes the original problem without the regression, but for now we'll have to live with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants