diff options
author | Guo Xiang Tan <tgx_world@hotmail.com> | 2017-09-25 20:29:43 +0800 |
---|---|---|
committer | Guo Xiang Tan <tgx_world@hotmail.com> | 2017-09-25 20:29:43 +0800 |
commit | 89711d99b08b5ace8aa5b7394e2ccedb302d118f (patch) | |
tree | a5d378d9fe9183842d9f44c4d76b55f1c3a77281 /activerecord/lib/active_record | |
parent | ab08f33f312c20638b9a7c38ee6318727c7f107d (diff) | |
download | rails-89711d99b08b5ace8aa5b7394e2ccedb302d118f.tar.gz rails-89711d99b08b5ace8aa5b7394e2ccedb302d118f.tar.bz2 rails-89711d99b08b5ace8aa5b7394e2ccedb302d118f.zip |
PERF: Restore memoization when preloading associations.
Benchmark Script
```
require 'active_record'
require 'benchmark/ips'
require 'ruby-prof'
require 'memory_profiler'
require 'byebug'
ActiveRecord::Base.establish_connection(ENV.fetch('DATABASE_URL'))
ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define do
create_table :users, force: true do |t|
t.string :name, :email
t.integer :topic_id
t.timestamps null: false
end
create_table :topics, force: true do |t|
t.string :title
t.timestamps null: false
end
end
attributes = {
name: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
email: 'foobar@email.com'
}
class Topic < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :topic
end
100.times do
User.create!(attributes)
end
users = User.first(50)
Topic.create!(title: 'This is a topic', users: users)
Benchmark.ips do |x|
x.config(time: 10, warmup: 5)
x.report("preload") do
User.includes(:topic).all.to_a
end
end
```
Before
```
Calculating -------------------------------------
preload 26.000 i/100ms
-------------------------------------------------
preload 265.347 (± 3.0%) i/s - 2.652k
```
After
```
Calculating -------------------------------------
preload 39.000 i/100ms
-------------------------------------------------
preload 406.053 (± 1.7%) i/s - 4.095k
```
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r-- | activerecord/lib/active_record/reflection.rb | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 82ab2415e1..032df925bf 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -425,7 +425,6 @@ module ActiveRecord def initialize(name, scope, options, active_record) super - @automatic_inverse_of = nil @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type") @foreign_type = options[:foreign_type] || "#{name}_type" @constructable = calculate_constructable(macro, options) @@ -609,12 +608,14 @@ module ActiveRecord # If it cannot find a suitable inverse association name, it returns # +nil+. def inverse_name - options.fetch(:inverse_of) do - @automatic_inverse_of ||= automatic_inverse_of + unless defined?(@inverse_name) + @inverse_name = options.fetch(:inverse_of) { automatic_inverse_of } end + + @inverse_name end - # returns either false or the inverse association name that it finds. + # returns either +nil+ or the inverse association name that it finds. def automatic_inverse_of if can_find_inverse_of_automatically?(self) inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym @@ -631,8 +632,6 @@ module ActiveRecord return inverse_name end end - - false end # Checks if the inverse reflection that is returned from the |