Clojure simple threaded web server performance test.
After reading David Nolen’s post about Aleph I was curious to see how scalable a simple Clojure threaded web application could be when paired with good old Postgres 8.4. To make things just slightly more realistic, two queries will be generated per request, and a basic listing of the data will be produced.
I’m running this experiment on an iMac with a 2.8 Ghz Intel Core i7 with 8 gigs of memory.
Here’s the code:
And here’s a screen capture of the output page produced:
The tests will be run with apache bench set to make one thousand requests with a concurrency of fifty. The tests will be run ten times and the results averaged.
ab -n 1000 -c 50 http://localhost:8080/
The first pass will use straight non-pooled connections.
Results: 668 requests a second.
Not exactly speedy, but that’s expected due to the high cost of making a connection to the database for every request.
Now let’s will switch to connection pooling. Eliminating the connection overhead should increase performance significantly.
Result: 901 requests a second.
Better, but not nearly as large a difference as I was expecting. Perhaps changing the maximum connections to the database will improve the performance. Let’s bump the maximum connections to 3 and try again.
Result: 2203 requests a second.
A large improvement. Setting the maximum connections to 3 increased performance rather dramatically. Now let’s try setting the maximum connections to 50 to match the concurrency we are using in apache bench.
Result: 3138 requests a second.
Again a large improvement. Not a surprise as the optimal connection level for the work load at hand was readily apparent. Time for one more experiment: Setting the maximum connections to 1000. (postgres.conf must be adjusted to allow one thousand connections.)
Result: 3065 requests a second.
Basically the same as the previous run. So blindly setting the maximum connections higher does not pay off in improved performance in this circumstance.
The simple experiment illustrated here is merely the tip of a very large optimization ice-burg. I know very little about actually tuning Postgres. There are other connection pool libraries out there that could potentially be faster. Operations folks experienced in these matters may be able to squeeze out even more performance for very little complexity cost.
My personal conclusion is that it’s extremely unlikely that any project I’m building will ever need the additional raw speed offered by event based servers. The complexity is, quite simply, not worth the cost. Every situation is different but trading complexity for raw speed, unless it’s your only competitive advantage, seems like a fools errand.
If you want to play around yourself, the code is available on Github.
