Rails provides a few caching techniques, one of which is a fragment cache. The fragment cache is a dead-easy way to cache bits of your view.
After checking that your queries are doing sensible things, the next often slowest part of the Rails stack is view rendering, especially if there’s lots of URL generation involved. More often than not you don’t want to cache the entire page as static HTML and bypass Rails altogether, instead, you want to retain the dynamic goodness of a web app and just cache the slow bits.
I recently added fragment caching to the toolmantim.com home page. Before I added fragment caching my production.log looked a little something like this:
Completed in 0.12385 (8 reqs/sec) | Rendering: 0.10077 (81%) | DB: 0.02210 (17%) | 200 OK [http://toolmantim.com/]
After fragment caching 2 parts of the application layout and the body of the home page my production.log looks a little something like this:
Completed in 0.00615 (162 reqs/sec) | Rendering: 0.00583 (94%) | DB: 0.00000 (0%) | 200 OK [http://toolmantim.com/]
A 17 times speed increase in rendering time for the cost of 2 dead-simple cache sweeper models, 4 lines of controller code and 6 lines of view code. I’d say that was worth the 30 minutes it took to implement.
There’s a few other things besides fragment caching I could have used to increase performance–optimise the DB call by SELECTing only the needed columns, or write a helper that generates Article and Comment URLs instead of relying on Rails to figure it all out for me–but I wanted to see how fast I could make the page whilst still keeping it within the Rails stack, and keeping things flexible.
Look out for tomorrow’s post when I’ll show how easy it is to take advantage of fragment caching in your own applications.





August 21st, 2006 at 10:53 pm
What is the overall performance of Rails like then? Both of those benchmarks look fairly poor considering that page isnt exactly doing complicated stuff?
August 21st, 2006 at 11:48 pm
The above two lines from the log aren’t benchmarks that can be looked usefully outside of comparing them to one another.
Rails scales well on both the server and code complexity sides of the equation, but the base-line performance can be less than applications written on other languages, frameworks and platforms (but does that really say anything… as there’s always something that’s going to perform faster than what you’re using).
Really, it’s too hard to answer your question as it’s so open-ended. I will say though that Rails is written on the tenet that servers are cheap, brains are expensive and that performance that’s “good enough” for 99% of people is ok. There’s plenty of room for the other 1% of people to optimise if they have the need.
August 22nd, 2006 at 12:25 am
Fair point, thanks for the answer :)
August 22nd, 2006 at 1:01 am
It’s interesting to note though that Ruby 2 should speed things up dramatically, as (by the looks of it) YARV will be the core engine
September 12th, 2006 at 7:38 am
I think the other optimizations you mention at the end would not even be worth the effort.
SELECTing fewer columns doesn’t normally speed up the database. I guess if your database is on a slow link or your selecting a ton of data you might eliminate some overhead, but I think the speed improvement would usually be negligible.
The second optimization of using helpers instead of url_for (link_to) depends mostly on the performance of the routing code, which I haven’t looked at all that closely. I guess I’ve heard one or two complaints about it in the past, but it probably also depends on the complexity of your routes.rb file.
Before doing any optimization I’d do some profiling first. And always keep Amdahl’s law in mind. In most web applications the database is the bottleneck, and aside from judicious use of ActiveRecord and a deep understanding of SQL, fragment caching is gonna be your next line of attack.
December 19th, 2006 at 10:34 pm
[…] One of the great things about Rails is that when you hit a DB/rendering performance bottleneck, you can often alleviate it with caching. If page caching is not an option (for example, most of your pageviews are from authenticated users), fragment caching is also a great option which can give you just the exact HTML or partial that you need. […]
March 1st, 2007 at 1:41 am
[…] Rails Performance Tips Common Performance Problems in Rails - Pros and con between SQLSessionStore and MemChacheStore session containers, tips on optimizing queries, and general information regarding how to avoid slow helpers. The Adventures of Scaling: Stage 1, Stage 2, Stage 3, Stage 4 - A detailed explanation a Rails production architecture. Optimizing Rails Resource Usage - A short list of top Rails optimization tips, which include the proper use of caching. Sustainable Performance with Ruby on Rails - A 58 page PDF presentation describing railsbench, caching, session performance, and efficient Ruby code. Rails performance tips - A discussion on eager loading, excluding unnecessary columns, indexing database columns, and caching. Top 10 Ruby on Rails performance tips - Provides great tips to optimize your ruby code and how to handle finders. Performance related changes in Rails 1.1 - Discussion of performance enhancements in rails 1.1. Rails performance and caching, Part 2 - A discussing of Rails performance using caching. Stefan Kaes - Rails Performance - RubyConf 2006 conference notes on the Rails Performance presentation given by Stefan Kaes. Stefen Kaes - Optimizing Rails - Another post on the Rails 2006 presentation by Stefan Kaes on Rails Performance. Rails performance with FastCGI and Apache - A blog post on performance with Apache. Rails Performance Tool Box - A list of tools that come in handy when optimizing a Ruby on Rails application, which include query analyzer, query trace, and mtop. Rails Caching Documentation - Documentation for action, page, and fragment caching. The effect of using Rails fragment caching - Goes over the performance boost of using fragment caching. […]