I have a new post on using Jetty with PHP-FPM that, if you think this is interesting, you should check that one out.

(this post has a sister post on Apache’s event MPM compared to Nginx)

I was originally going to write a blog post about why NginX with FastCGI was faster than Apache with mod_php. I had heard a while ago that NginX running PHP via FastCGI was faster than Apache with mod_php and have heard people swear up and down that it was true. I did a quick test on it a while back and found some corresponding evidence.

Today I wanted to examine it more in depth and see if I could get some good numbers on why this was the case. The problem was that I couldn’t. IIRC, it was for a Magento installation.

To test I did a simple “hello, world” script. Why something simple? Because once you’re in the PHP interpreter there should be no difference in performance. So why not just do a blank page? It’s because I wanted to have some kind of bi-directional communication. The intent was to test the throughput of the web-server, not PHP. So I wanted to be spending as little time in PHP as possible but still test the data transmission.

The baseline tests show the following.

Apache w/ mod_php

Total transferred: 3470000 bytes HTML transferred: 120000 bytes Requests per second: 2395.73 [#/sec] (mean) Time per request: 4.174 [ms] (mean) Time per request: 0.417 [ms] (mean, across all concurrent requests) Transfer rate: 811.67 [Kbytes/sec] received

NginX with PHP-FPM

Total transferred: 1590000 bytes HTML transferred: 120000 bytes Requests per second: 5166.39 [#/sec] (mean) Time per request: 1.936 [ms] (mean) Time per request: 0.194 [ms] (mean, across all concurrent requests) Transfer rate: 801.82 [Kbytes/sec] received

Apache was able to dish out 2400 requests per second compared with 5200 requests per second on NginX. That was more than I had seen before and so I did an strace -c -f on Apache to see what came up. -c shows cumulative time on system calls, -f follows forks. The result for the top 10?

% time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 33.65 0.042063 4 10003 getcwd 16.10 0.020127 2 10001 writev 16.00 0.019994 2 10001 shutdown 10.54 0.013179 0 51836 40118 open 9.01 0.011263 1 20008 semop 5.22 0.006522 0 54507 10002 read 2.53 0.003158 0 10024 write 1.91 0.002386 0 88260 66483 close 1.57 0.001959 245 8 clone 1.16 0.001455 0 54832 384 stat64

getcwd? Why? Then I remembered that I had AllowOverride (.htaccess) turned on. So I re-ran the test with AllowOverride set to None.

Total transferred: 3470000 bytes HTML transferred: 120000 bytes Requests per second: 5352.41 [#/sec] (mean) Time per request: 1.868 [ms] (mean) Time per request: 0.187 [ms] (mean, across all concurrent requests) Transfer rate: 1813.40 [Kbytes/sec] received

At 5352 requests per second Apache actually was outperforming NginX. But what about if more data was transferred? So I created about 100k of content and tested again.

Apache

Total transferred: 1051720000 bytes HTML transferred: 1048570000 bytes Requests per second: 2470.24 [#/sec] (mean) Time per request: 4.048 [ms] (mean) Time per request: 0.405 [ms] (mean, across all concurrent requests) Transfer rate: 253710.79 [Kbytes/sec] received

NginX

Total transferred: 1050040000 bytes HTML transferred: 1048570000 bytes Requests per second: 2111.08 [#/sec] (mean) Time per request: 4.737 [ms] (mean) Time per request: 0.474 [ms] (mean, across all concurrent requests) Transfer rate: 216476.53 [Kbytes/sec] received

This time the difference was even greater. This all makes sense. mod_php has PHP embedded in Apache and so it should be faster. If you’re running only PHP on a web server then Apache still seems to be your best bet for performance. And if you are seeing a significant performance difference then you should check if AllowOverride is turned on. If it is, try moving that into httpd.conf and try again.

If you are running mixed content, such as adding CSS, JS and images, then NginX will provide better overall performance but it will not run PHP any faster. It will also respond better to denial of service attacks better, but a CDN is generally better at mitigating that risk.

But if you are running pure PHP content on a given server, Apache seems to still be the best bet for the job.

[UPDATED]

Here’s a chart of the throughput difference