diff options
author | Simon Coffey <simon@urbanautomaton.com> | 2018-03-30 22:45:57 +0100 |
---|---|---|
committer | Simon Coffey <simon@urbanautomaton.com> | 2018-04-02 20:50:33 +0100 |
commit | eede8d8130558cb46aba8736bd63e8a28e37eac2 (patch) | |
tree | 2fd0d317f82cc3577d6f1d6b93e35432861ef648 /actionview/lib | |
parent | 073168358740b33831f0963242ba1de1d0ddb0cc (diff) | |
download | rails-eede8d8130558cb46aba8736bd63e8a28e37eac2.tar.gz rails-eede8d8130558cb46aba8736bd63e8a28e37eac2.tar.bz2 rails-eede8d8130558cb46aba8736bd63e8a28e37eac2.zip |
Add `action_view.finalize_compiled_template_methods` config option
ActionView::Template instances compile their source to methods on the
ActionView::CompiledTemplates module. To prevent leaks in development
mode, where templates can frequently change, a finalizer is added that
undefines these methods[1] when the templates are garbage-collected.
This is undesirable in the test environment, however, as templates don't
change during the life of the test. Moreover, the cost of undefining a
method is proportional to the number of descendants a class or module
has, since the method cache must be cleared for all descendant classes.
As ActionView::CompiledTemplates is mixed into every
ActionView::TestCase (or in RSpec suites, every view spec example
group), it can end up with a very large number of descendants, and
undefining its methods can become very expensive.
In large test suites, this results in a long delay at the end of the
test suite as all template finalizers are run, only for the process to
then exit.
To avoid this unnecessary cost, this change adds a config option,
`action_view.finalize_compiled_template_methods`, defaulting to true,
and sets it to false in the test environment only.
[1] https://github.com/rails/rails/blob/09b2348f7fc8d4e7191e70e06608c5909067e2aa/actionview/lib/action_view/template.rb#L118-L126
Diffstat (limited to 'actionview/lib')
-rw-r--r-- | actionview/lib/action_view/railtie.rb | 8 | ||||
-rw-r--r-- | actionview/lib/action_view/template.rb | 7 |
2 files changed, 14 insertions, 1 deletions
diff --git a/actionview/lib/action_view/railtie.rb b/actionview/lib/action_view/railtie.rb index 12bdc642d4..12d06bf376 100644 --- a/actionview/lib/action_view/railtie.rb +++ b/actionview/lib/action_view/railtie.rb @@ -10,6 +10,7 @@ module ActionView config.action_view.embed_authenticity_token_in_remote_forms = nil config.action_view.debug_missing_translation = true config.action_view.default_enforce_utf8 = nil + config.action_view.finalize_compiled_template_methods = true config.eager_load_namespaces << ActionView @@ -45,6 +46,13 @@ module ActionView end end + initializer "action_view.finalize_compiled_template_methods" do |app| + ActiveSupport.on_load(:action_view) do + ActionView::Template.finalize_compiled_template_methods = + app.config.action_view.delete(:finalize_compiled_template_methods) + end + end + initializer "action_view.logger" do ActiveSupport.on_load(:action_view) { self.logger ||= Rails.logger } end diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb index 0c4bb73acb..1c8713d6e3 100644 --- a/actionview/lib/action_view/template.rb +++ b/actionview/lib/action_view/template.rb @@ -9,6 +9,9 @@ module ActionView class Template extend ActiveSupport::Autoload + mattr_accessor :finalize_compiled_template_methods + self.finalize_compiled_template_methods = true + # === Encodings in ActionView::Template # # ActionView::Template is one of a few sources of potential @@ -307,7 +310,9 @@ module ActionView end mod.module_eval(source, identifier, 0) - ObjectSpace.define_finalizer(self, Finalizer[method_name, mod]) + if finalize_compiled_template_methods + ObjectSpace.define_finalizer(self, Finalizer[method_name, mod]) + end end def handle_render_error(view, e) |