I finally had a bit of time to do some Typo benchmarking over the weekend and (as usual) found that my instincts were all wrong.
So I set up a test environment under Xen, running Typo r683, PostgreSQL, Apache 2, FastCGI, Ruby 1.8.2, and Rails 0.13.1. I didn’t do any Apache or Postgres tuning–I just ran them out of the box.
Here’s what I found:
|Cache Type||Requests per second|
That really wasn’t what I’d expected. The action cache underperformed my expectations by a factor of 20.
I then did a bit of experimentation. I created a new uncached action in my test Typo setup that did nothing but
render :text => 'foo', :layout => false, just to see if the caching system was slowing things down. Result? 10 requests/second. Then I created a new Rails project from scratch and added a new controller with the same action, and saw the same results. Still 10 requests/second.
However, in Rails’s logs, it said that it handled the request in 2 ms, and I should be seeing 500 hits/sec for the “foo” page. So something is adding an extra 98 ms to each request. I’m still hunting for this–I don’t know if it’s something Xen-related on my system, an artifact of my Apache config, or what.
I’ve tried upgrading to Rails 0.14.0, but that’s a whole other article.
- The page cache is really, really fast.
- The action cache is a substantial improvement over the uncached case–about 10x on this system–but can’t touch the performance of the page cache.
- Changing the concurrency settings on
aband/or the number of FastCGI backends in use didn’t make a substantial performance difference. Settings 2-15 gave roughly the same results.
caches_action_with_paramsis slightly faster then the stock action cache.
- Moving the action/fragment cache from the FileStore (Typo default) to MemoryStore gives no real performance boost. Moving to the MemCacheStore is a substantial performance hit (~2 hits/sec vs 10 hits/sec).
- Adding a new uncached action in ArticlesController that simply returns a fixed string (
render :layout => false, :text => 'foo') is no faster then the action cache.
- Moving the new action from the previous step to a Controller of its own doesn’t help.
- Removing all of the routes except the default
:controller/:action/:idroute doesn’t help, either.
Frankly, on this hardware, I don’t seem to be able to get more then 10 requests/sec out of Rails no matter what I do. I’m pretty sure that this is a mistake, so I’ll post a followup when I figure out what’s wrong.
Update 1: Another datapoint. Running an example Ruby FCGI on this box gives me 832 hits per second. So whatever the problem is, it’s not fundamental to Ruby FCGI on this box. So I need to look into Rails and see what’s happening.
Update 2: Making some progress. Apparently I screwed up when I tested a new, standalone Rails FCGI app before (forgot to restart FCGI?). This time, I got 130 req/sec, which is a vast improvement over the 10 req/sec that I was seeing before. Most of that speed hit seems to come from using Postgres for session storage. Unfortunately, even after making that change, my null controller is still only getting 40 req/sec with Typo. Transporting the same controller to a blank Rails project gives me 130 req/sec with the same code. Watching strace, it looks like something is forcing Typo to reload the
digest/md5 module for every hit. Unfortunately, I can’t figure out how that’s happening–my
environment.rb is identical between the two trees, as is my
database.yml. I’ll get back to this later; I have other things that I need to finish today.