diff options
author | Sean Griffin <sean@thoughtbot.com> | 2015-02-06 12:05:29 -0700 |
---|---|---|
committer | Sean Griffin <sean@thoughtbot.com> | 2015-02-06 12:10:47 -0700 |
commit | ec6c98f7d11e53811fbaa13ed521386f53011630 (patch) | |
tree | 76aebb1c1c66af0a73c31cb279ceac9a9139fbfd /activerecord/lib/active_record | |
parent | f4e8d67367c7670ac5bbc75f001cd5c2b2deed30 (diff) | |
download | rails-ec6c98f7d11e53811fbaa13ed521386f53011630.tar.gz rails-ec6c98f7d11e53811fbaa13ed521386f53011630.tar.bz2 rails-ec6c98f7d11e53811fbaa13ed521386f53011630.zip |
Significantly improve the performance of `_read_attribute` on JRuby
The `&block` form is more than twice as fast as the manual form of
delegation (and is the code I'd rather write anyway). Unfortunately,
it's still twice as slow on MRI. However, this is enough of a hotspot to
justify giving JRuby special treatment.
I can't currently provide benchmarks in the context of Active Record,
since the JDBC adapters still aren't updated for 4.2, but the actual
work performed (assuming it's been read at least once already) will have
nearly the same performance characteristics as
https://gist.github.com/sgrif/b86832786551aaee74de.
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/read.rb | 13 | ||||
-rw-r--r-- | activerecord/lib/active_record/attribute_set.rb | 12 |
2 files changed, 21 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 24e30b6608..0d989c2eca 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -69,9 +69,18 @@ module ActiveRecord # This method exists to avoid the expensive primary_key check internally, without # breaking compatibility with the read_attribute API - def _read_attribute(attr_name) # :nodoc: - @attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? } + if defined?(JRUBY_VERSION) + # This form is significantly faster on JRuby, and this is one of our biggest hotspots. + # https://github.com/jruby/jruby/pull/2562 + def _read_attribute(attr_name, &block) # :nodoc + @attributes.fetch_value(attr_name.to_s, &block) + end + else + def _read_attribute(attr_name) # :nodoc: + @attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? } + end end + alias :attribute :_read_attribute private :attribute diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb index 9142317646..013a7d0e01 100644 --- a/activerecord/lib/active_record/attribute_set.rb +++ b/activerecord/lib/active_record/attribute_set.rb @@ -31,8 +31,16 @@ module ActiveRecord attributes.each_key.select { |name| self[name].initialized? } end - def fetch_value(name) - self[name].value { |n| yield n if block_given? } + if defined?(JRUBY_VERSION) + # This form is significantly faster on JRuby, and this is one of our biggest hotspots. + # https://github.com/jruby/jruby/pull/2562 + def fetch_value(name, &block) + self[name].value(&block) + end + else + def fetch_value(name) + self[name].value { |n| yield n if block_given? } + end end def write_from_database(name, value) |