Web Hosting Blog

Welcome to our web hosting blog for all the latest web hosting info. Learn how to get the most out of your VPS host server.


Over the past few days I've been optimizing the server that this site and many others that I own reside on. Today I got to the question; Should I use php-cgi or php-fpm with my nginx web server?  Just so that you have an idea of what I'm running on - I'm using the Intel(R) Atom(TM) CPU D2500  @ 1.86GHz with a 180GB Crucial SSD (can't remember the model but isn't really relevant right now) and the openvz container I'm running this in has both cores and 1.5GB of RAM. This is nothing too spiffy but I expect a lot from my hardware 🙂 I should probably also tell you that the configuration of my software stack was already done by the lowendbox bootstrap script that I used a long time ago to get a fast working setup and that is found here http://lowendbox.com/blog/wordpress-cheap-vps-lowendscript/ Now we can get to the good part! I did a bit of googling and found the program Tsung to simulate users and benchmark my server while providing me with pretty statistics. Here is my tsung configuration for reference.
<?xml version="1.0"?> <!DOCTYPE tsung SYSTEM "/usr/share/tsung/tsung-1.0.dtd"> <tsung loglevel="notice" version="1.0"> <clients> <client host="localhost" weight="1" maxusers="500" cpu="1"/> </clients> <servers> <server host="" port="80" type="tcp"/> </servers> <load> <arrivalphase phase="1" duration="10" unit="minute"> <users maxnumber="15000" arrivalrate="8" unit="second"/> </arrivalphase> <arrivalphase phase="2" duration="10" unit="minute"> <users maxnumber="15000" arrivalrate="8" unit="second"/> </arrivalphase> <arrivalphase phase="3" duration="30" unit="minute"> <users maxnumber="20000" arrivalrate="3" unit="second"/> </arrivalphase> </load> <sessions> <session probability="100" name="ab" type="ts_http"> <for from="1" to="10000000" var="i"> <request> <http url="/index.php" method="GET" version="1.1"/> </request> </for> </session> </sessions> </tsung>
I pointed tsung to the following php file.
<?php echo ' <html> <head> </head> <body>What are you doing here? Get out.</body> </html> '; ?>
I then ran tsung on my server and tried to browse to the same php script that tsung was benchmarking(above) and kept getting 502's over and over and over. I was sick of the 502 bad gateway requests! (This means that php-cgi wasn't able to handle my request but nginx was working properly.) I knew with this default setup I wasn't serving very many requests per second. Here are some things I noticed with php-cgi on my server while benchmarking.
  1. The server load was over 20 at any given time and the server was crawling.
  2. RAM was completely consumed within a few seconds of benchmarking.
  3. Didn't notice any %wa though which is good.
  4. No matter what I set PHP_FCGI_CHILDREN to in the config, I never could load the php script in my browser while tsung was running and the load stayed the same.
I am no expert with php-cgi but through all of my googling I couldn't really find a way to optimize it further than these options -
fastcgi_connect_timeout 60; fastcgi_send_timeout 180; fastcgi_read_timeout 180; fastcgi_buffer_size 128k; fastcgi_buffers 4 256k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; fastcgi_intercept_errors on;
Now for some php-cgi statistics!


I ran this benchmark for quite a long time but as you can see from the beginning of the graph we only got about 100/sec good responses vs 1000/sec bad responses. From what I'm seeing it looks like it got even worse the longer I ran the benchmark, after 100 seconds it looks to have dropped to about 10/sec good responses and 1600/sec bad responses.
Code Highest Rate Total number
200 94.3 / sec 73900
502 1860.7 / sec 3008207
Highest rate of good responses was 94.3/sec - just terrible! So then I installed php-fpm. Php-fpm stands for php fastcgi process manager, so from what I understand it's basically using the php-cgi api and managing the processes ( layer on top of a layer ). Here are some things I noticed about php-fpm
  1. The server load was around 2 at any given time and the server responsiveness was great.
  2. RAM wasn't completely consumed until running tsung for about 30 seconds.
  3. Still not noticing any %wa much like php-cgi
  4. changing pm.max_children actually seemed to affect 200's per second up to a sweet spot
  5. I was actually able to browse to the php script now while tsung was running!
  6. Out of the box php-fpm performed 100% better with no optimizations.
Now for some more stats from php-fpm!


  I didn't run this benchmark for very long. php-fpm uses its own process queue and everything goes in there up until nginx starts timing out processes after 30 seconds. You can see after the nginx 30 second timeout we started getting some 502's. The lowest this seemed to drop was about 110 good requests per second. I believe I also increased worker connections to 2048 from 1024 in nginx so more requests were getting through which seems to have resulted in overall more 502's when I ran out of ram.
Code Highest Rate Total number
200 1037.4 / sec 48743
502 2896.8 / sec 216105
Our highest rate is now over 10 times the old highest rate at 1037.4 good requests per second. On top of that we almost completed as many requests with a 200 response in 110 seconds as php-cgi completed in 2250 seconds! As far as pm.max_children goes I ended up setting that to 16, any more of these seemed to do no good for my server config. From my tests as you can see php-fpm is definitely the way to go for me because it's out of the box configuration with very little optimization seemed to work WAY better than php-cgi. There may be some php-cgi modifications you experts can do that will make php-cgi perform closer to php-fpm that I am unaware of and couldn't find through my research. Criticism/questions on my benchmarking and general write up are highly encouraged!


Enter your name and address below to subscribe to our mailing list and receive special offers.