Optimizing php-fpm the Promet Way
Ever wondered how you can tweak your server's configuration to get the most out of what you’re paying? Here are some good techniques that we like to use at Promet.
Disclaimer: This doesn’t mean that it’s the perfect server setup, but it’s a good start. Every requirement is unique and understanding how it works is always the first step. Having good documentation in the form of a blog post saves us a lot of time and effort so we would like to share our experience as well.
At Promet, we use nginx and php-fpm for our servers. One good benefit of this against using the good old mod_php from apache is that nginx can act as a proxy and will serve the static files directly, only those with extension of php are passed to fpm-php.
Optimizing php-fpm is tricky at first but once you understand how it works then it’s quite a bit easier than you think. We are using debian base system so the default location of the the configuration file is /etc/php5/fpm/pool.d/www.conf.
Choosing the best strategy
There are three strategies on how php-fpm allocate memory: static, dynamic and on-demand.
- Static - a fixed number of a process you ask to allocate.
- Dynamic - allocate a fixed amount of processes but will dynamically increase once your load increases.
- ondemand - nothing will start as long as there are no requests to be served.
Choosing which type of strategy is quite confusing at first, but out of the three you should always use Dynamic and ondemand. This allows you to dynamically allocate memory for your web servers to efficiently manage your server resources.
We will be using ondemand strategy, which basically means that it would start or kill new process based on demand. The advantage of this is the simplicity because you only need to determine one setting, “max_children”, and you can leave everything else as default.
Let’s take the following server specification as an example:
For now we will be using the default values of the packages. We will calculate the optimal setting based on the usage of a process. So you first need to have some traffic.
Determining memory per child process
We need to determine how much memory per child process of php-fpm is using for calculating the final value. I use a script called ps_mem to get some statistics of my processes and memory.
# Download the script first
# and run it like this:
python ps_mem.py | grep php5
the output should give you something like this:
1.8 GiB + 145.5 MiB = 1.9 GiB php5-fpm (41)
This means php-fpm is using in total 1.9 GiB with 41 Processes. After converting the value in Megabyte, we will divide it by the number of processes. This will tell us: How much each child process (41) is consuming.
1900 MiB/41 Processes = 46.34 MiB
48.59MB memory / Processes
We can now calculate the number of process php-fpm can calculate via this simple formula:
max_children = (Total Number of Memory - 1000MB) / FPM Memory per Process
We reserved 1000MB for other process like mysql, nginx, etc.
max_children = (4000 MB - 1000 MB) / 48.59
max_children = 62.5
You can now set the pm.max_children to have maximum of 62.5.
And that’s it, folks! I hope this has been as informative to you as it is to us.
As always, we love to hear any constructive criticism and how this would help everyone, please contact us if you think something can be improved.