1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

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
This commit is contained in:
Rafael Mendonça França 2015-09-08 01:04:22 -03:00
parent 9bf772d936
commit 0675210c95

View file

@ -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