At work, we're developing a brand new in-house CMS based on the Symfony framework. As it uses no mod_rewrite rules or other Apache dependencies and is a "clean break" for us, I figured it would be an ideal candidate for benchmarking under LigHTTPd, comparing it to Apache 2.2 in order to give me some statistics to compliment my last blog entry on the subject.
The results from the "ab" Apache-benchmark tool are pretty stunning - although I'm still at a loss as to explain just why LigHTTPd is so much faster. The configuration of everything apart from the webserver is identical. I'm running on a Sun Ultra 20 with 2Gb of RAM and Solaris 10 01/06. I have a shared document root, and two separately, identically configured zones, one running Apache 2.2.3 with prefork MPM, the other running LigHTTPd. PHP on both is 5.1.4, built using exactly the same compiler (Sun Studio 11) and flags for the Apache 2.2 SAPI and Fast-CGI build. Apache is using PHP loaded as a DSO, whilst LigHTTPd is running PHP through a socket, with 8 pre-forked PHP child processes :
fastcgi.server = (
".php" => ((
"socket" => "/tmp/php-fastcgi.socket",
"bin-path" => "/usr/local/php/bin/php",
"bin-environment" => (
"PHP_FCGI_CHILDREN" => "8",
"PHP_FCGI_MAX_REQUESTS" => "10000"
),
"bin-copy-environment" => (
"PATH", "SHELL", "USER"
),
"min-procs" => 1,
"max-procs" => 1,
))
)
The page in question is just the initial login page to the CMS. There's no database access at all, so no communication with any system external to the web server. It's just straight Symfony processing, using the current trunk.
Read on for the results...
I first ran ab with a concurreny of 3, for 50 requests in total
.
Apache results
Concurrency Level: 3
Time taken for tests: 7.845 seconds
Complete requests: 50
Failed requests: 0
Broken pipe errors: 0
Total transferred: 241250 bytes
HTML transferred: 220150 bytes
Requests per second: 6.37 [#/sec] (mean)
Time per request: 470.70 [ms] (mean)
Time per request: 156.90 [ms] (mean, across all concurrent requests)
Transfer rate: 30.75 [Kbytes/sec] received
Connnection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 154 449 291.7 415 1357
Waiting: 154 449 291.8 414 1357
Total: 154 449 291.7 415 1357
LigHTTPD results
Concurrency Level: 3
Time taken for tests: 2.927 seconds
Complete requests: 50
Failed requests: 0
Broken pipe errors: 0
Total transferred: 236600 bytes
HTML transferred: 220150 bytes
Requests per second: 17.08 [#/sec] (mean)
Time per request: 175.62 [ms] (mean)
Time per request: 58.54 [ms] (mean, across all concurrent requests)
Transfer rate: 80.83 [Kbytes/sec] received
Connnection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 2
Processing: 57 106 146.8 59 809
Waiting: 57 105 146.9 58 808
Total: 57 106 146.8 59 809
Analysis
LigHTTPd clearly wins on this one, both in terms of overall time, and
the number of requests it managed to handle per second. I was interested to see how well it scaled though, so upped the number of requests to 1,000 and concurrency to 20. The difference is even more pronounced :
Apache Summary
Time taken for tests: 169.914 seconds
Total transferred: 4825000 bytes
HTML transferred: 4403000 bytes
Requests per second: 5.89 [#/sec] (mean)
Time per request: 3398.28 [ms] (mean)
Time per request: 169.91 [ms] (mean, across all concurrent requests)
Transfer rate: 28.40 [Kbytes/sec] received
Lighttpd Summary
Time taken for tests: 58.354 seconds
Total transferred: 4732000 bytes
HTML transferred: 4403000 bytes
Requests per second: 17.14 [#/sec] (mean)
Time per request: 1167.08 [ms] (mean)
Time per request: 58.35 [ms] (mean, across all concurrent requests)
Transfer rate: 81.09 [Kbytes/sec] received
Now, that's impressive. Just compare the number of requests a second, transfer rate and overall time taken for the tests. LigHTTPd blows Apache away, and what's just as interesting is what's going on behind the scenes. Apache sustained 60-70% CPU utilisation and around 300Mb RSS size during that run, LigHTTPD and the FastCGI processes stuck at a constant 118Mb RSS. CPU utilisation did peak up to 70% at top, but was around 40% for most of the test.
Conclusion
I'm even more impressed with LigHTTPd now I have some numbers to back me up, yet I'm still at a loss as to explain exactly why it is so much fast. Could it be that Apache adds an even greater overhead to PHP running as a DSO module ? We already know LigHTTPd is far batter than Apache at serving static content and it's general efficiency is better; but that's nothing particularly new, people have been offloading static content from Apache for years. But it looks like it could really make a massive difference to dynamic content as well. Time to do some more investigating...
Tuesday, May 8. 2007 at 21:09 (Reply)
Next time use the Worker MPM. Of course PHP doesn't recommend using mod_php with worker MPM which is why you should use FastCGI.
I'm a bit at a loss why you didn't bench both daemons with FastCGI. The performance difference between prefork and worker is well-known too...
Wednesday, July 11. 2007 at 19:35 (Reply)
Plus, for our uses, I've had numerous issues with the Worker MPM particularly in relation to SSL which effectively ruled it out.
However, you're quite right - for fariness' sake, I should have benchmarked Apache's FastCGI/Worker combination. When I get a spare moment, I'll re-run the tests and see what comes out on top.
Thursday, October 11. 2007 at 14:17 (Reply)
Have you already re-run the tests with both daemons running fcgi?
Tuesday, September 15. 2009 at 08:07 (Link) (Reply)
Sunday, October 25. 2009 at 21:07 (Reply)
http://www.lighttpd.net/2007/2/3/raw-io-performance
Beyond that it is much stripped down and doesn't replicate many of the DSO modules that ship with Apache - AUTH, PROXY, URL_REWRITE etc
Thursday, January 21. 2010 at 04:00 (Reply)
Friday, January 22. 2010 at 12:25 (Reply)
I haven't revisited this for years (we never ended up going with LigHTTPd in production) so it would be interesting to run these tests again on up-to-date hardware and software...
Friday, March 5. 2010 at 01:48 (Link) (Reply)
You can read more about how to serve (in my tests) up to 9000 req/s in my blog, but that is not dynamic data! There is a huge differense between serving static and dynamic data. (2)
(1) http://en.wikipedia.org/wiki/Moore's_law
(2) http://www.vvvegard.net/blog/category/varnish/
Kind regards,
Vegard
Wednesday, October 12. 2011 at 11:12 (Link) (Reply)