ActiveRecord initialization optimizations #29215
ActiveRecord model initialization got a lot slower between Rails 4.2 and Rails 5 — 2-5x slower or more, depending on the specific circumstances.
This PR includes optimizations that speed up model initialization by approximately 2x for STI models and 1.3x for non-STI models, as compared to vanilla 5.1, returning performance somewhat closer (but by no means entirely) to 4.2 levels.
We have been running these optimizations on our high-traffic Rails 5.0.2 app in production for the last few days without issue. We are seeing an average response time speedup of just over 4%, compared to vanilla Rails 5.0.2, with certain actions showing speedup of 5-15%. (Our app depends heavily on STI and uses a caching scheme that results in many model initializations even on cache hits; YMMV.)
Running the benchmarks
These benchmarks were produced by this benchmarking script using Ruby 2.3.3 on OS X. To run them yourself, clone the gist, then:
Potential future work
With these patches in place, the remaining ActiveRecord initialization slowness introduced in Rails 5.0 seems to be related to changes in
I'm no expert in this area of the Rails codebase, and I could not find a relevant PR that describes the rationale behind these changes, but I think any further optimizations would be much more involved than the straightforward changes made here.
Skip the call to #dup, since it does a shallow copy of attributes, which is wasted effort, since #deep_dup then replaces that shallow copy with a #deep_dup of the given attributes. This change addresses slowness in ActiveRecord initialization introduced starting in Rails 5.0.
This change addresses slowness in ActiveRecord initialization introduced starting in Rails 5.0.
Memoize the #column_defaults class property, as ActiveRecord does for other properties in this module. This change addresses slowness in ActiveRecord initialization introduced starting in Rails 5.0. This method's performance has not changed with Rails 5, but it is now called much more frequently than before: every time an STI model is instantiated.