Adjusting child processes for PHP-FPM (Nginx)


The following warning message appears in the logs:

[26-Jul-2012 09:49:59] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 8 idle, and 58 total children
[26-Jul-2012 09:50:00] WARNING: [pool www] server reached pm.max_children setting (50), consider raising it

It means that there are not enough PHP-FPM processes.


We need to calculate and change these values based on the amount of memory on the system:


pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

– the following command will help us to determine the memory used by each (PHP-FPM) child process:

ps -ylC php-fpm --sort:rss

The RSS column shows non-swapped physical memory usage by PHP-FPM processes in kilo Bytes.

On an average each PHP-FPM process took ~75MB of RAM on my machine.

Appropriate value for pm.max_children can be calculated as:

pm.max_children = Total RAM dedicated to the web server / Max child process size – in my case it was 85MB

The server has 8GB of RAM, so:

pm.max_children = 6144MB / 85MB = 72

I left some memory for the system to breath. You need to take into account any other services running on the machine while calculating memory usage.

I’ve changed the settings as follow:

pm.max_children = 70
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 35
pm.max_requests = 500

Please note that very high values does not mean necessarily anything good.

You can check an average memory usage by single PHP-FPM process with this handy command:

ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'

You can use the same steps above to calculate the value for MaxClients for Apche web server – just substitute the php-fpm with httpd.


Determining the correct number of child processes for PHP-FPM on NGinx

If you are using a NGinx webserver with PHP5-FPM (or PHP-FPM) most likely you will have to adjust the out of the box settings of php-fpm. If your php5-fpm.log file contains the following error:

[26-Mar-2015 10:10:04] WARNING: [pool www] server reached pm.max_children setting (35), consider raising it
[26-Mar-2015 12:04:52] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)

This means you do not have enough processes available for php-fpm.

Based on your realtime logging data, it is easy to determine the correct settings for the php-fpm configuration on your server. The exact settings are based on the memory available to your cloud server or virtual server, but be aware that you have to take the other processes also into account, they also nibble on those resources (example: MySQL). Never simply use 100% memory available in the virtual machine!

The following steps need to be adjusted in the /etc/php5/fpm/pool.d/www.conf file (typical location on Debian although the path may vary):

pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 4
pm.max_spare_servers = 8

To find the correct values, you will have to measure how much memory a proces consumes. Be warned though this is only possible on a server where the website has a stable memory usage per proces, in other words for a shared hosting environment with different websites and different developped code the memory usage per proces will seriously fluctuate!
The following line (executed in shell) will give you valuable output:

ps -ylC php5-fpm --sort:rss

The name php5-fpm matches your process name. If it possible it is named php-fpm on your server.

The column RSS contains the average memory usage in kilobytes per process.

S     0 24439     1  0  80   0  6364 57236 -      ?        00:00:00 php5-fpm
S    33 24701 24439  2  80   0 61588 63335 -      ?        00:04:07 php5-fpm
S    33 25319 24439  2  80   0 61620 63314 -      ?        00:02:35 php5-fpm

In this example 61588 kilobytes or converted about +- 60 Mb per process.

Another option is to get the average of one php5-fpm process:

ps --no-headers -o "rss,cmd" -C php5-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"Mb") }'

To get the correct value for the number of pm.max_children we will have to check how much memory our cloud or vps server can use for the php-fpm process and divide that total by the average size in Mb of our just checked process.

An example: if our cloud server has 4 GB RAM and a MySQL database service is running as well that consumes at least 1 GB our best aim is to get 4 – 1 – 0,5 (marge) GB = 2,5 GB RAM or 2560 Mb.

pm.max_children brings us to 2560 Mb / 60 Mb = 42 max_children

We have made the following changes in our www.conf file in the php5-fpm pool:

pm.max_children = 40
pm.start_servers = 15
pm.min_spare_servers = 15
pm.max_spare_servers = 25
pm.max_requests = 500

Restart the php5-fpm service and see if the server behaves in a correct manner and allocates memory as configured.