Apaches and Lighttpds and Mongrels, oh my!

April 2nd, 2007

After fighting with concurrency issues with the OSU Libraries implementation of LibraryFind, I decided to do some investigation into the best way to implement the webserver / application server. Ruby suffers from a severe lack of threadiness. That’s my word, don’t steal it! 

After scouring the Internet… the whole Internet… I found quite a bit of discussion about how this particular combination was great, but this other combination was even better and thisother combination was horrible. *gasp* 

So, being the perfectionist that I am (my wife would disagree), I decided to put them to the test, just like the MythBusters

I put together a couple of different test cases. I call these “Round 3″ and “Round4″? Where did rounds 1 and 2 go? I don’t know. 

Test Round 3 consists of executing 500 non-cached queries against the LibraryFind searcherer, /record/retrieve, using 30 different search terms in quasi-random order. I was hoping to get together a list of 500 different search terms, but my fingers got tired after 30, so I stuck with that. It seemed to do the trick, though! To test concurrency I ran 5 concurrent transactions. The server I was testing on is a dual processor, dual core Opteron (from Sun Microsystems. If I say their name enough, maybe they’ll give me free stuff… ok, this was a Sun Fire X4200!) so much more than 5 concurrent searches (4 really) is just testing how fast your kernel’s SMP or NUMA code is. 

Test Round 4 consists of executing 500,000 cached queries against the same searcherer, /record/retrieve, this time using the exact same search term, over and over… and over. Again, I ran 5 concurrent transactions to put the system under as much load as it could reasonably tolerate without getting annoyed with me. Not a true load test, but a good idea of how well the system can retrieve records from cache and spit them back to the user. 

The results were somewhat, but not entirely surprising. Of course, using plain CGI worked reasonably well, but was slow. It was so slow, in fact, that I ended up killing the Apache/CGI test after it had completed only about 8600 of its 500,000 transactions because it had already taken longer than Apache/mongrel had for the FULL 500,000… yes, Apache/CGI took more time to complete less than 2% of the test than Apache/mongrel. 

Between web servers, Apache 2.2.4 in its worker MPM mode seemed to perform slightly better than Lighttpd 1.4.13 when proxying to mongrel. The opposite was true for Apache 2.0.59/FastCGI (I couldn’t get FastCGI to run against 2.2.4) and Lighttpd 1.4.13/FastCGI. Lighttpd seems to perform better when using FastCGI. After the horrible showing for Apache/CGI I didn’t even try Lighttpd/CGI. I also could not get Apache to work well with scgi_rails. 

All in all, I found the combination of Apache 2.2.4 using mod_proxy_balancer to talk to 10 instances of mongrel 1.0.1 (using mongrel_cluster to manage the mongrel instances) to be the fastest, most efficient combination. I also like mongrel_cluster’s ability to manage the independent mongrel instances.

Below are some links to a summary of my findings, and some graphs of the test durations and transaction rates. 

Comments are closed.