-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Fix confusing exception in ActiveSupport delegation #15187
Fix confusing exception in ActiveSupport delegation #15187
Conversation
@@ -72,7 +72,7 @@ def manufacturer | |||
|
|||
def type | |||
@type ||= begin | |||
nil.type_name | |||
:thing_without_same_method_name_as_delegated.name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a new test instead of changing one that already exist?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, just read your comment on the description, so yes it seems fine to change.
…ception Fix confusing exception in ActiveSupport delegation
Performance regression: 1fb9e6e |
I found delegate to be a bottleneck during integration tests. Here is the test case: ```ruby require 'test_helper' class DocumentsIntegrationTest < ActionDispatch::IntegrationTest test "index" do get '/documents' assert_equal 200, response.status end end Minitest.run_one_method(DocumentsIntegrationTest, 'test_index') StackProf.run(mode: :wall, out: 'stackprof.dump') do 3000.times do Minitest.run_one_method(DocumentsIntegrationTest, 'test_index') end end ``` Top of the stack: ``` [aaron@TC integration_performance_test (master)]$ stackprof stackprof.dump ================================== Mode: wall(1000) Samples: 23694 (7.26% miss rate) GC: 1584 (6.69%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 7058 (29.8%) 6178 (26.1%) block in Module#delegate 680 (2.9%) 680 (2.9%) ActiveSupport::PerThreadRegistry#instance 405 (1.7%) 405 (1.7%) ThreadSafe::NonConcurrentCacheBackend#[] 383 (1.6%) 383 (1.6%) Set#include? 317 (1.3%) 317 (1.3%) ActiveRecord::Base.logger 281 (1.2%) 281 (1.2%) Rack::Utils::HeaderHash#[]= 269 (1.1%) 269 (1.1%) ActiveSupport::Notifications::Fanout::Subscribers::Evented#subscribed_to? 262 (1.1%) 262 (1.1%) block (4 levels) in Class#class_attribute 384 (1.6%) 246 (1.0%) block (2 levels) in Class#class_attribute ``` According to @eileencodes's tests, this speeds up integration tests so that they are only 1.4x slower than functional tests: Before: INDEX: Integration Test: 153.2 i/s - 2.43x slower After: INDEX: Integration Test: 275.1 i/s - 1.41x slower
" else", | ||
" #{exception unless allow_nil}", | ||
" end", | ||
"end" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guys, I've small suggestion. I hope this code would be easier to read & maintain:
method_def = <<-RUBY.lines.join(';')
def #{method_prefix}#{method}(#{definition})
_ = #{to}
if !_.nil? || nil.respond_to?(:#{method})
_.#{method}(#{definition})
else
#{exception unless allow_nil}
end
end
RURY
You can add .strip_heredoc
if it matters :)
This caused a performance regression since we were decided to do the nil check in run time not in the load time. See #15187 (comment)
This caused a performance regression since we were decided to do the nil check in run time not in the load time. See #15187 (comment)
Follow-up on #15186. I decided to change the existing test, as it did intend to cover this case, but failed to do so.