aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/core.rb
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2019-04-22 14:41:00 +0900
committerRyuta Kamizono <kamipo@gmail.com>2019-04-22 14:41:00 +0900
commitb6828fc91531ae0cc0a0f216705dd19112596301 (patch)
treeccff8b37db7f15d86fe128085640827269ba8eea /activerecord/lib/active_record/core.rb
parent02b5b8cb4357fe0eda3a5cc0afcfe3ff9f300806 (diff)
downloadrails-b6828fc91531ae0cc0a0f216705dd19112596301.tar.gz
rails-b6828fc91531ae0cc0a0f216705dd19112596301.tar.bz2
rails-b6828fc91531ae0cc0a0f216705dd19112596301.zip
PERF: 20% faster pk attribute access
I've realized that `user.id` is 20% slower than `user.name` in the benchmark (https://github.com/rails/rails/pull/35987#issuecomment-483882480). The reason that performance difference is that `self.class.primary_key` method call is a bit slow. Avoiding that method call will make almost attribute access faster and `user.id` will be completely the same performance with `user.name`. Before (02b5b8cb): ``` Warming up -------------------------------------- user.id 140.535k i/100ms user['id'] 96.549k i/100ms user.name 158.110k i/100ms user['name'] 94.507k i/100ms user.changed? 19.003k i/100ms user.saved_changes? 25.404k i/100ms Calculating ------------------------------------- user.id 2.231M (± 0.9%) i/s - 11.243M in 5.040066s user['id'] 1.310M (± 1.3%) i/s - 6.565M in 5.012607s user.name 2.683M (± 1.2%) i/s - 13.439M in 5.009392s user['name'] 1.322M (± 0.9%) i/s - 6.615M in 5.003239s user.changed? 201.999k (±10.9%) i/s - 1.007M in 5.091195s user.saved_changes? 258.214k (±17.1%) i/s - 1.245M in 5.007421s ``` After (this change): ``` Warming up -------------------------------------- user.id 158.364k i/100ms user['id'] 106.412k i/100ms user.name 158.644k i/100ms user['name'] 107.518k i/100ms user.changed? 19.082k i/100ms user.saved_changes? 24.886k i/100ms Calculating ------------------------------------- user.id 2.768M (± 1.1%) i/s - 13.936M in 5.034957s user['id'] 1.507M (± 2.1%) i/s - 7.555M in 5.017211s user.name 2.727M (± 1.5%) i/s - 13.643M in 5.004766s user['name'] 1.521M (± 1.3%) i/s - 7.634M in 5.018321s user.changed? 200.865k (±11.1%) i/s - 992.264k in 5.044868s user.saved_changes? 269.652k (±10.5%) i/s - 1.344M in 5.077972s ```
Diffstat (limited to 'activerecord/lib/active_record/core.rb')
-rw-r--r--activerecord/lib/active_record/core.rb6
1 files changed, 3 insertions, 3 deletions
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index b9046fcc1a..068ebf3c09 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -174,8 +174,7 @@ module ActiveRecord
record = statement.execute([id], connection)&.first
unless record
- raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
- name, primary_key, id)
+ raise RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id)
end
record
end
@@ -398,7 +397,7 @@ module ActiveRecord
##
def initialize_dup(other) # :nodoc:
@attributes = @attributes.deep_dup
- @attributes.reset(self.class.primary_key)
+ @attributes.reset(@primary_key)
_run_initialize_callbacks
@@ -570,6 +569,7 @@ module ActiveRecord
end
def init_internals
+ @primary_key = self.class.primary_key
@readonly = false
@destroyed = false
@marked_for_destruction = false