Helpers vs. Partials - A Performance Question
Ben Scofield, Former Viget
Article Category:
Posted on
Have you ever looked in your development log and seen something like the following?
Processing FoosController#show (for ...) [GET] Session ID: BAh7CDoOcmV0dXJuX3R... SQL (0.000869) SHOW TABLES SQL (0.000931) SHOW TABLES Image Load (0.000465) SELECT images.* FROM ... [...] Rendered entries/_detail (0.00221) Rendered entries/_detail (0.00103) Rendered entries/_detail (0.00118) Rendered entries/_detail (0.00092) Rendered entries/_detail (0.00107) Rendered entries/_detail (0.00069) Rendered entries/_detail (0.00215) Rendered entries/_detail (0.00113) Rendered entries/_detail (0.00113) Rendered entries/_detail (0.00098) Rendered entries/_detail (0.00098) Rendered entries/_detail (0.00087) Rendered entries/_detail (0.00079) Rendered entries/_detail (0.00086) Rendered entries/_detail (0.00079) Rendered entries/_detail (0.00087) Rendered entries/_detail (0.00076) Rendered entries/_detail (0.00081) Rendered shared/_nav (0.00207) Rendered shared/_analytics (0.00011) Rendered shared/_footer (0.00188) Completed in 1.63867 (0 reqs/sec) | Rendering: 0.40653 (24%) ...
These sorts of entries in the log have always felt like a code smell to me - even when some sort of markup reuse is obviously necessary (so you can't just do it inline), I can't help but think that there's some significant cost to rendering the same file over and over again. So after a long time of thinking about it, I finally got around to doing some benchmarks comparing generating markup in a helper method, rendering a partial repeatedly for a collection, and rendering a partial with the :collection
key. For each method, I use apache benchmark to hit a page 1000 times (with 2 simultaneous requests); each request generated 1000 divs like this:
<div> <span>index</span> <a href="#">link</a> </div>
Here's what I found:
Method | Time per Request | Requests/Second |
---|---|---|
Helper | 186.998 ms | 10.70 |
Partial | 438.244 ms | 4.56 |
Partial for collection | 266.068 ms | 7.52 |
So it looks like there is a cost to rendering a partial repeatedly, but that cost can be reduced by using the :collection
key, and reduced even further by generating the markup in a helper method. Of course, the helper method can be a smell of its own, but if performance is an issue it may be worth a look.
Note: This is an unscientific test, so feel free to respond with your own benchmarks.