提交 0668c22a 编写于 作者: K Kir Shatrov

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
上级 904f1a87
......@@ -58,6 +58,12 @@ class Railtie < Rails::Railtie # :nodoc:
end
end
initializer "action_mailer.eager_load_actions" do
ActiveSupport.on_load(:after_initialize) do
ActionMailer::Base.descendants.each(&:action_methods) if config.eager_load
end
end
config.after_initialize do |app|
options = app.config.action_mailer
......
......@@ -77,5 +77,11 @@ class Railtie < Rails::Railtie #:nodoc:
end
end
end
initializer "action_controller.eager_load_actions" do
ActiveSupport.on_load(:after_initialize) do
ActionController::Metal.descendants.each(&:action_methods) if config.eager_load
end
end
end
end
......@@ -238,6 +238,66 @@ def change
assert_instance_of Pathname, Rails.public_path
end
test "does not eager load controller actions in development" do
app_file "app/controllers/posts_controller.rb", <<-RUBY
class PostsController < ActionController::Base
def index;end
def show;end
end
RUBY
app "development"
assert_nil PostsController.instance_variable_get(:@action_methods)
end
test "eager loads controller actions in production" do
app_file "app/controllers/posts_controller.rb", <<-RUBY
class PostsController < ActionController::Base
def index;end
def show;end
end
RUBY
add_to_config <<-RUBY
config.eager_load = true
config.cache_classes = true
RUBY
app "production"
assert_equal %w(index show).to_set, PostsController.instance_variable_get(:@action_methods)
end
test "does not eager load mailer actions in development" do
app_file "app/mailers/posts_mailer.rb", <<-RUBY
class PostsMailer < ActionMailer::Base
def noop_email;end
end
RUBY
app "development"
assert_nil PostsMailer.instance_variable_get(:@action_methods)
end
test "eager loads mailer actions in production" do
app_file "app/mailers/posts_mailer.rb", <<-RUBY
class PostsMailer < ActionMailer::Base
def noop_email;end
end
RUBY
add_to_config <<-RUBY
config.eager_load = true
config.cache_classes = true
RUBY
app "production"
assert_equal %w(noop_email).to_set, PostsMailer.instance_variable_get(:@action_methods)
end
test "initialize an eager loaded, cache classes app" do
add_to_config <<-RUBY
config.eager_load = true
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册