diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2015-09-08 01:04:22 -0300 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2015-09-08 01:04:22 -0300 |
commit | 0675210c959153ae826f3ceccb6b4fbcb2783daa (patch) | |
tree | 3fc59aae78cadaec5a161f4ee992d74cb069d3dd /activerecord/lib | |
parent | 9bf772d936c3236267eb8f7a09dde21226125234 (diff) | |
download | rails-0675210c959153ae826f3ceccb6b4fbcb2783daa.tar.gz rails-0675210c959153ae826f3ceccb6b4fbcb2783daa.tar.bz2 rails-0675210c959153ae826f3ceccb6b4fbcb2783daa.zip |
Memoized reflections accessor
Its value never change since associations are defined at class load time
so there is no need to build the hash everytime the method is called.
Before this change:
Calculating -------------------------------------
reflections 804.000 i/100ms
-------------------------------------------------
reflections 8.213k (±26.2%) i/s - 36.180k
After this change:
Calculating -------------------------------------
reflections 24.548k i/100ms
-------------------------------------------------
reflections 1.591M (±25.7%) i/s - 7.364M
Benchmark script:
require 'bundler/setup'
require 'active_record'
require 'benchmark/ips'
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define do
100.times do |i|
create_table "users#{i}", force: true
end
create_table :cars, force: true do |t|
100.times do |i|
t.references "users#{i}"
end
end
end
class Car < ActiveRecord::Base
100.times do |i|
belongs_to "users#{i}".to_sym
end
end
Benchmark.ips do |x|
x.report('reflections') { Car.reflections }
end
Diffstat (limited to 'activerecord/lib')
-rw-r--r-- | activerecord/lib/active_record/reflection.rb | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 5360db6a19..e7f56d09e3 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -32,6 +32,7 @@ module ActiveRecord end def self.add_reflection(ar, name, reflection) + ar.clear_reflections_cache ar._reflections = ar._reflections.merge(name.to_s => reflection) end @@ -67,18 +68,22 @@ module ActiveRecord # # @api public def reflections - ref = {} - _reflections.each do |name, reflection| - parent_reflection = reflection.parent_reflection + @__reflections ||= begin + ref = {} - if parent_reflection - parent_name = parent_reflection.name - ref[parent_name.to_s] = parent_reflection - else - ref[name] = reflection + _reflections.each do |name, reflection| + parent_reflection = reflection.parent_reflection + + if parent_reflection + parent_name = parent_reflection.name + ref[parent_name.to_s] = parent_reflection + else + ref[name] = reflection + end end + + ref end - ref end # Returns an array of AssociationReflection objects for all the @@ -118,6 +123,10 @@ module ActiveRecord def reflect_on_all_autosave_associations reflections.values.select { |reflection| reflection.options[:autosave] } end + + def clear_reflections_cache #:nodoc: + @__reflection = nil + end end # Holds all the methods that are shared between MacroReflection, AssociationReflection |