I'm having a PHP based web application running on Apache server which has considerable amount of php processing in back end. Since the overall performance is low I worked on improving the performance of the application. First I followed techniques such as client side caching, gzip enabling, js-css minifying which improved the performance upto a good extend.
In order to further improve the performance I wanted to try out server level improvement. So I tried to compare the application performance by hosting it on Apache and Nginx servers.
In Apache I user Apache + mod-php and in Nginx I used Nginx + php-fpm for this comparison. As most of the tutorials explained I configured the number of Nginx workers equal to the number of cores in my processor. I used jmeter to do the stress testing and following are the graphs I could generate out of it.
In all these graphs x-axis is each request I sent and y-axis is milliseconds for getting response for each request.
Access the login page
Submit the login page
Access home page
I could only perform the testing upto 100 concurrent users logged in within 1 second because it started dropping requests after then in both server setups.
There was a little improvement on performance in Nginx than Apache but it was not a major difference where it's worth to change all my server architecture from Apache to Nginx. And when I observe the server resource utilization also I didn't find much of difference between Nginx and Apache
When I went through other comparisons people have done, I found that they claim Nginx is much more faster in concurrent accesses such as following graph shows.
http://www.eschrade.com/wp-content/uploads/2014/01/event-mpm-nginx.gif
But I was unable to observe any major difference of performance in Nginx over Apache even with 100 concurrent access within 1 second.
Following are my questions.
I did a bit more research on this and found that Nginx will perform well with static resources and not with other dynamic content delivery such as php processing which needs to done with the help of external application such as php-fpm. So if your web application has a performance bottleneck on php processing then replacing Apache with Nginx will not be a solution.
Following article explains a details research done on comparing static contend delivery and php script result delivery using Apache + mod_php and Nginx + php-fpm.
http://blog.a2o.si/2009/06/24/apache-mod_php-compared-to-nginx-php-fpm/
Following are the conclusion points described in the above article.
Conclusion or “should you switch from Apache to Nginx?”
Longer answers are here:
I have a website running with load balancing of 3 servers. 2 of them are running on nginx with PHP-FPM (new ones). However the main server is on Apache + PHP FastCGI hittng roughly 40% traffic. Recently I thought of changing Apache also to nginx; so I installed nginx on the same server for a different IP and did some tests. But surprisingly, Apache could generate the page in 10-20 milliseconds on each hit but nginx takes 60-70 milliseconds. nginx is faster for static files, but if you have a CDN there is no need to worry about static content. Apache is a great server. But try FastCGI and not the PHP module.
Despite there being a lot of claims that it's faster, or supposed to be, no, it's not supposed to be faster, at least not unconditionally.
Exactly which is faster, mod_php or ext-fpm, hasn't been proven and it's likely to vary. In respect to performance you have three considerations, theory, implementation, use case, resources and load.
In theory, mod_php is the fastest achievable. With mod_php the web server and interpreter directly communicate, they share the same resources and memory space. With ext-fpm you have separate processes that communicate not as directly and that must duplicate resources.
Traditionally separate processes are popular because they tend to have greater flexibility in respect to things such as running as many different users, different versions concurrently, etc. Many people also use multiple process systems as they can't be bothered to free()
, fclose()
, etc.
While ext-fpm, using FastCGI, is an attempt to make the separate process model meet its maximum theoretical speed, the maximum theoretical speed is still slower than the maximum theoretical speed of unified processes.
Finding out which is fastest can be difficult. Other people's tests wont be reliable even if well orchestrated as they may not be relevant to your use case and your setup. In your own tests you may make one faster than the other but it doesn't mean someone can't come along and change that. That someone could be you with more time and understanding at your disposal.
The implementation of mod_php isn't necessarily one that brings it to its maximum theoretical speed. The two might not be as far apart as people might expect especially as quite often the SAPI overhead can turn out to be trivial in comparison to everything else that goes on when serving a static request. Many benchmarks are having to test with virtually noop scripts so that the difference appears significant.
It has become a popular belief that ext-fpm "is fast". There are many forces which persist this, some of which are innocent, others draw from incompetence and some are down right manipulative.
Often when people see a different result they fail to appreciate why. The intimate details of their process, measurements and traffic are left out. People then often attempt to repeat these successes and fail leaving endless search results of people asking why it's not faster. The big one is people finding success when using a multiple-process based MPM with mod_php while having a static content heavy load. These cases can be especially deceptive as the load from static requests can bounce back onto PHP.
Another common mistake is for people to also test two different configurations. The configuration for php-fpm might be more optimised than that for mod_php. Sometimes it can be as simple as people optimising everything about the one they expect to be faster while neglecting the original. This is especially relevant where people might do things such as not check whether requests were successful while also changing things such as the memory limit or maximum execution time. A lot of things can change in the configuration when people are only meant to change the SAPI, sometimes even unavoidably, sometimes even transparently. A common example might be that the limits on the webserver might be insufficient to maximise utilisation of the server's resources where as ext-fpm will be able to spawn additional processes to take advantage of additional cores. It's common to see people move things such as routing over from PHP to the webserver for FPM.
Compared to mod_php with a multiple-process-single-threaded MPM, ext-fpm is a good contender with a lot of all round benefits though greater performance isn't strictly guaranteed. Though if your load is entirely serving PHP requests then Apache is already more of less doing what ext-fpm would otherwise be doing.
There's also a discrepancy between things such as latency versus throughput and cycles versus bytes versus waits.
In theory, the way forward is php-zts with either ngx_php or mod_php. The big caveat is that php-zts hasn't gotten nearly the uptake nor care and attention as php-nts such that it introduces overhead to PHP execution itself which makes it very hard to compete with php-fpm at present. The implementation does not bring it into the realm of reaching its optimum. In some cases suboptimum might be an understatement. Many people are concerned about the reliability of threaded PHP which may or may not impact you. It certainly wont be as much of a concern if you're only serving dynamic content and not running a shared hosting service. This appear to potentially be a fear campaign orchestrated by Apache. There should be enough people using php-zts for platforms where it's the only option for it to be relatively stable.
There are other options though they may be more hands on. It's even possible to open a unix socket yourself, parse the FCGI and handle it asynchronously with things such as select. The caveat of event driven in PHP is that most of the major high level IO libraries such as MySQL don't support it in a unified fashion.
php-swoole is starting to look promising though it's early days yet. The situation with php-fpm, mod_php and php-zts is a mess.