aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2015-10-15 14:44:01 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2015-10-15 14:44:28 -0700
commit960de47f0eef79d234eb3cfc47fabb470fef1529 (patch)
tree14ec87c60341fa46b74dc3413a8a62ae2de4b419 /activesupport
parent3b61027092517ac9fd2736d38673c27fedd08c1b (diff)
downloadrails-960de47f0eef79d234eb3cfc47fabb470fef1529.tar.gz
rails-960de47f0eef79d234eb3cfc47fabb470fef1529.tar.bz2
rails-960de47f0eef79d234eb3cfc47fabb470fef1529.zip
drop array allocations when iterating over the hash
`each_with_object` allocates an array for each kv pair. Switching to the slightly more verbose but less allocatey `each_pair` eliminates array allocations. Eliminating this allocation returns AR objects to have constant array allocations regardless of the number of columns the object has. Here is test code: ```ruby require 'active_record' class Topic < ActiveRecord::Base end 20.times do |i| Process.waitpid fork { ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:' ActiveRecord::Base.connection.instance_eval do create_table(:topics) do |t| t.string :title, limit: 250 t.string :author_name t.string :author_email_address t.string :parent_title t.string :type t.string :group i.times do |j| t.string :"aaa#{j}" end t.timestamps null: true end end ObjectSpace::AllocationTracer.setup(%i{type}) Topic.create title: "aaron" # heat cache result = ObjectSpace::AllocationTracer.trace do 10.times do |i| Topic.create title: "aaron #{i}" end end puts "#{Topic.columns.length},#{(result.find { |k,v| k.first == :T_ARRAY }.last.first / 10)}" } end ``` Before this commit: ``` 9,166 10,167 11,168 12,169 13,170 14,171 15,172 16,173 17,174 18,175 19,176 20,177 21,178 22,179 23,180 24,181 25,182 26,183 27,184 28,185 ``` After: ``` 9,157 10,157 11,157 12,157 13,157 14,157 15,157 16,157 17,157 18,157 19,157 20,157 21,157 22,157 23,157 24,157 25,157 26,157 27,157 28,157 ``` Left side is the number of columns, right is the number of allocations
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/lib/active_support/core_ext/object/deep_dup.rb4
1 files changed, 3 insertions, 1 deletions
diff --git a/activesupport/lib/active_support/core_ext/object/deep_dup.rb b/activesupport/lib/active_support/core_ext/object/deep_dup.rb
index 0e6962a378..8dfeed0066 100644
--- a/activesupport/lib/active_support/core_ext/object/deep_dup.rb
+++ b/activesupport/lib/active_support/core_ext/object/deep_dup.rb
@@ -39,7 +39,8 @@ class Hash
# hash[:a][:c] # => nil
# dup[:a][:c] # => "c"
def deep_dup
- each_with_object(dup) do |(key, value), hash|
+ hash = dup
+ each_pair do |key, value|
if key.frozen? && ::String === key
hash[key] = value.deep_dup
else
@@ -47,5 +48,6 @@ class Hash
hash[key.deep_dup] = value.deep_dup
end
end
+ hash
end
end