ActiveRecord#attributes optimization: minimize objects created #6687

Merged
merged 1 commit into from Jun 9, 2012

Conversation

Projects
None yet
3 participants
Contributor

tiegz commented Jun 9, 2012

What

I propose reverting to the old implementation of ActiveRecord#attributes (changed in c4809d9).

Why

The current way that attributes builds its attributes hash creates (n * 2) + 1 extraneous arrays, where n is the number of attribute keys. Switching back to the old implementation reduces this to 0.

For instance, I have a model with 43 columns; with Memprof (on 1.8.7) we can see that attributes normally creates 87 Arrays because of the map usage:

1.8.7 :010 > Memprof.track { my_record.attributes }
     87 /.../activerecord-3.2.5/lib/active_record/attribute_methods.rb:184:Array
      1 /.../activerecord-3.2.5/lib/active_record/attribute_methods.rb:184:__node__
      1 /.../activerecord-3.2.5/lib/active_record/attribute_methods.rb:184:Hash

Now when we switch back to the original implementation that builds a hash with each (despite having 2 more LOC), we can see the benefit:

1.8.7 :010 > Memprof.track { my_record.attributes }
      1 /.../activerecord-3.2.5/lib/active_record/attribute_methods.rb:184:Hash
      1 /.../activerecord-3.2.5/lib/active_record/attribute_methods.rb:179:Array

I didn't verify the object count in 1.9 myself, but I did a 1.9 GC profile and confirmed that GC did run fewer times overall with this change (over a large sample).

Note

afaik, attributes isn't actually used that often, however serializable_hash uses it. Since serializable_hash would most likely be used in apis where it's common to return lists of many records, it seems worthy of optimizing this method.

Member

josevalim commented Jun 9, 2012

Thanks. I think those appeared when removing the use of inject inside framework. It probably exists in other places.

josevalim merged commit eaeebc2 into rails:3-2-stable Jun 9, 2012

Owner

spastorino commented Jun 9, 2012

👍 I've changed master to use each_with_object f9cfe9a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment