Using Siege to Tune Apache on GNU/Linux

UPDATE: This article is now slightly dated. In the comments below, Null4Ever provides more contemporary kernel parameter settings.

Siege is a great tool to measure web site performance and establish benchmark metrics. What do you do if siege shows your performance stinks? This document illustrates how to tune your server and validate those tunings with siege.

For the purpose of this exercise we will tune a very old Linux server to effectively serve static content at a rate of 200 requests per second. We’ll start with an out-of-box apache configuration and build from there. By the way, when I say “old” I mean old:

There’s no two ways about it: that’s crappy. What steps can we take to improve that? An obvious place to look is the apache configuration. Is the server configured to handle 200 simulataneous connections? If apache is configured with less than 200 workers, then requests are queued until workers are available to handle them. Let’s check our config:

Sure enough, we have fewer workers than requests. Let’s bump those numbers in order to meet our requirement. While we’re at it, we’ll increase the initial pool so we pay less of a penalty to fork new workers:

After apache restart we find thirty-three httpd processes in memory. With a bigger pool in memory, it’s easier to accomodate a large pool of incoming requests. With the expansion of our workers pool, we have the capacity to meet our load requirement. Let’s see how these changes affected our performance:

Our transaction rate improved by nearly 3.5 per second. This is because requests spent less time waiting for a worker to handle them. If you watch the web server’s socket table during a siege, one thing stands out. The number of sockets in TIME_WAIT. This what I saw during the last run:

Ben: $ netstat -a | grep TIME_WAIT | wc -l
8081

If we could recycle those connections, we could improve our performance. The kernel parameter that controls TIME_WAIT reuse is ‘net.ipv4.tcp_tw_recycle’. The sysctl command will enable you to view and set kernel parameters. Let’s check the value on our web server:

Ben: $ sysctl net.ipv4.tcp_tw_recycle
net.ipv4.tcp_tw_recycle = 0

We’re not reusing sockets in TIME_WAIT. Let’s change it and view our results:

Our transactions per second sky-rocketed to 327.39! That’s a significant improvement but we still have a problem. Notice the elapsed time. I stopped the siege short of a minute because it was hung. In run after run, siege was hung at about 10,200 transactions. In fact, every time I run the siege it hangs at that number. We’re exhausting something, but what? Let’s check our kernel parameters and see what we find: