How to Tune PHP-FPM to Improve Performance on Server

If your PHP web application is randomly lagging and from visual observations of CPU/memory usage your server is not getting maxed out, it might mean you need to tune PHP.


The following warnings in your PHP log file are an indication of this issue:


[21-Oct-2020 12:38:11] WARNING: [pool www] server reached pm.max_children setting (10), consider raising it
[21-Oct-2021 12:38:11] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 9 total children


By default, PHP is limited to use only a small portion of a machine's resources. If your website is getting thousands of page views a day and sporadically hangs there is a good chance you'll need to give PHP access to more resources.


Open the PHP-FPM Configuration File

The first step is to open the PHP-FPM configuration file.


sudo nano /etc/php/7.2/fpm/pool.d/www.conf


Notehow to check PHP version.


Step 2

The next step to look for the following constants:


pm = dynamic
pm.max_children = 5
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.start_servers = 2


Let's go through each and adjust them to allow PHP to use more server resources, improving performance under high load.


Set the pm to dynamic, to allow a dynamic number of child processes based on the pm.max_children, pm.min_spare_servers, pm.max_spare_servers values.


pm = dynamic


The pm.max_children, controls the max number of alive child processes. To calculate roughly how many to allow, take RAM and divide it by the average PHP process size.


Let's say the system has 10GB of RAM and each PHP process is around 12MB we would use the following formula to calculate the max number of processes to potentially use:


10000MB / 12MB = 833


Setting pm.max_children to 833 would allow PHP to use all the RAM on the system. We should leave at least 30% RAM free for other programs; depending on whether your server is used for things other than HTTP requests this might want to be more.


For my particular scenario 600 seemed like a good value for pm.max_children:


pm.max_children = 600


pm.min_spare_servers is the minimum number of children in 'idle' state (waiting to process). Set this value to 2:


pm.min_spare_servers = 2 


pm.max_spare_servers is the maximum number of children in 'idle' state (waiting to process). This value should be between x2 and x4 the number of system cores. For a quad-core system, anywhere between 8 and 16 max_spare_servers should be optimal:


pm.max_spare_servers = 16


pm.start_servers is the number of children created on startup. This value should be around half the value of max_spare_servers and not exceed the pm.max_children value.


pm.start_servers = 8


The final step is to restart the PHP service to apply the changes.


sudo service php7.2-fpm restart