Faster alternatives to ActiveRecord::Base.to_xml (Rails Performance Series)







With that scenario, the 1ActiveRecord::Base.to_xml call looks something like this:


The alternative is definitely more work:

 1h = {:attr1=>parent_object.attr1, :attr2=>parent_object.attr2} # ... etc
 3h[:child_objects] = parent.child_objects.map do |child|
 4  h2 = {:attr1=>child.attr1, :attr2=>child.attr2} # ... etc
 6  h2[:other_objects] = child.other_objects.map do |other|
 7    h3 = {:attr1=>other.attr1, :attr2=>other.attr2} # ... etc
 8  end
10  h2

Note that we’re actually still using a form of 1to_xml — it’s just 1Hash.to_xml instead.

There are some ways this could be streamlined, such as using 1parent.attributes to pull the list of attributes, or even an array of wanted attributes. I skipped that here to make the example easier to understand.

This method does have a couple benefits. One is that you can use more intelligent logic in regard to selecting the 1child_objects to include. For example: 1parent.child_objects.all(:limit=>10, :order=>'id desc') if you wanted just the last ten child objects.

Beyond that, and the focus of this posting, I found that the above resulted in a 2-3x speed increase. While I haven’t dug really far into the matter, it appears that the Rails magic that figures out what associations to include and the associated reflection has a heavy overhead.

I still use 1ActiveRecord::Base.to_xml much of the time, but the above option is nice for frequently requested actions with large, deep object trees.

tags: activerecord, performance, xml, ruby, rails