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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eager load controller actions to reduce response time of the first request #29559

Merged
merged 1 commit into from Aug 11, 2017

Conversation

Projects
None yet
4 participants
@kirs
Member

kirs commented Jun 24, 2017

On the first request, ActionController::Base#action_methods computes
and memoizes
the list of available actions. With this PR we move this expensive operation into eager load step to reduce response time of the first request served in production.

This also reduces the memory footprint when running on forking server like Unicorn.

all credit goes to @casperisfine. I'm just pushing this patch from Shopify into upstream 馃槉

@rafaelfranca @Edouard-chin

@rails-bot

This comment has been minimized.

Show comment
Hide comment
@rails-bot

rails-bot Jun 24, 2017

r? @matthewd

(@rails-bot has picked a reviewer for you, use r? to override)

rails-bot commented Jun 24, 2017

r? @matthewd

(@rails-bot has picked a reviewer for you, use r? to override)

Show outdated Hide outdated railties/test/railties/engine_test.rb
Show outdated Hide outdated actionpack/lib/action_controller.rb
Show outdated Hide outdated actionpack/lib/action_controller.rb
Show outdated Hide outdated actionpack/lib/action_controller.rb
Show outdated Hide outdated actionpack/lib/action_controller.rb
@kirs

This comment has been minimized.

Show comment
Hide comment
@kirs

kirs Jul 1, 2017

Member

@rafaelfranca I addressed your feedback. Thanks for review!

Member

kirs commented Jul 1, 2017

@rafaelfranca I addressed your feedback. Thanks for review!

@kirs

This comment has been minimized.

Show comment
Hide comment
@kirs
Member

kirs commented Jul 9, 2017

Show outdated Hide outdated railties/test/railties/engine_test.rb
Eager load controller and mailer actions
On the first request, ActionController::Base#action_methods computes
and memoized the list of available actions [1]. With this PR we move
this expensive operation into eager load step to reduce response time
of the first request served in production.

This also reduces the memory footprint when running on forking server
like Unicorn.

[1] https://github.com/rails/rails/blob/a3813dce9a0c950a4af7909111fa730a2622b1db/actionpack/lib/abstract_controller/base.rb#L66-L77
@kirs

This comment has been minimized.

Show comment
Hide comment
@kirs

kirs Jul 29, 2017

Member

@rafaelfranca thanks for review! I addressed the feedback. CI is green.

Member

kirs commented Jul 29, 2017

@rafaelfranca thanks for review! I addressed the feedback. CI is green.

@rafaelfranca rafaelfranca merged commit b9e0b4f into rails:master Aug 11, 2017

2 checks passed

codeclimate All good!
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@matthewd

This comment has been minimized.

Show comment
Hide comment
@matthewd

matthewd Nov 18, 2017

Member

@kirs @rafaelfranca this should be using eager_load_namespaces instead of after_initialize

Member

matthewd commented Nov 18, 2017

@kirs @rafaelfranca this should be using eager_load_namespaces instead of after_initialize

@kirs

This comment has been minimized.

Show comment
Hide comment
@kirs

kirs Nov 19, 2017

Member

@matthewd I tried it and the problem is that when eager_load_namespaces are loaded, the app code itself is not loaded yet. As a result ActionMailer::Base.descendants would always be [] when called within eager_load_namespaces.

In contrast, when we do it in after_initialize the app code is already loaded and ActionMailer::Base.descendants would include all classes that we expect.

Do you think it's a bigger problem that we should fix?

Member

kirs commented Nov 19, 2017

@matthewd I tried it and the problem is that when eager_load_namespaces are loaded, the app code itself is not loaded yet. As a result ActionMailer::Base.descendants would always be [] when called within eager_load_namespaces.

In contrast, when we do it in after_initialize the app code is already loaded and ActionMailer::Base.descendants would include all classes that we expect.

Do you think it's a bigger problem that we should fix?

@matthewd

This comment has been minimized.

Show comment
Hide comment
@matthewd

matthewd Nov 19, 2017

Member

Ah, hrmm. I was just looking at after_initialize callbacks and these stood out as seeming like they were in the wrong place. My direct concern is for other after_initialize callbacks that might rely on the fact "everything of note" has already occurred (e.g. AR).

At a more fundamental level, if we can't even implement our own eager loading using the callback designed for it... 馃槙

Maybe we should be splitting eager loading into two phases, constant loading vs "extra" loading/preparation?

Or maybe this is fine as it is. It just feels weird to me -- these components shouldn't really know about config.eager_load at all.

Member

matthewd commented Nov 19, 2017

Ah, hrmm. I was just looking at after_initialize callbacks and these stood out as seeming like they were in the wrong place. My direct concern is for other after_initialize callbacks that might rely on the fact "everything of note" has already occurred (e.g. AR).

At a more fundamental level, if we can't even implement our own eager loading using the callback designed for it... 馃槙

Maybe we should be splitting eager loading into two phases, constant loading vs "extra" loading/preparation?

Or maybe this is fine as it is. It just feels weird to me -- these components shouldn't really know about config.eager_load at all.

@kirs kirs deleted the kirs:eager-load-controller-actions branch Nov 21, 2017

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