Skip to content

Instantly share code, notes, and snippets.

@holmberd
Last active September 25, 2024 05:44
Show Gist options
  • Save holmberd/44fa5c2555139a1a46e01434d3aaa512 to your computer and use it in GitHub Desktop.
Save holmberd/44fa5c2555139a1a46e01434d3aaa512 to your computer and use it in GitHub Desktop.
Adjusting child processes for PHP-FPM (Nginx)

Adjusting child processes for PHP-FPM (Nginx)

When setting these options consider the following:

  • How long is your average request?
  • What is the maximum number of simultaneous visitors the site(s) get?
  • How much memory on average does each child process consume?

Determine if the max_children limit has been reached.

  • sudo grep max_children /var/log/php?.?-fpm.log.1 /var/log/php?.?-fpm.log

Determine system RAM and average pool size memory.

  • free -h
  • All fpm processes: ps -ylC php-fpm7.0 --sort:rss
  • Average memory: ps --no-headers -o "rss,cmd" -C php-fpm7.0 | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'
  • All fpm processes memory: ps -eo size,pid,user,command --sort -size | awk '{ hr=$1/1024 ; printf("%13.2f Mb ",hr) } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }' | grep php-fpm

Calculate max_children

Based on RAM

  • pm.max_children = Total RAM dedicated to the web server / Max child process size

  • System RAM: 2GB

  • Average Pool size: 85Mb

  • pm.max_children = 1500MB / 85MB = 17

Based on average script execution time

  • max_children = (average PHP script execution time) * (PHP requests per second)
  • visitors = max_children * (seconds between page views) / (avg. execution time)

Configure

sudo vim /etc/php/7.0/fpm/pool.d/www.conf

pm.max_children = 17
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_request = 1000
; Choose how the process manager will control the number of child processes.
; Possible Values:
;   static  - a fixed number (pm.max_children) of child processes;
;   dynamic - the number of child processes are set dynamically based on the
;             following directives:
;             pm.max_children      - the maximum number of children that can
;                                    be alive at the same time.
;
;             pm.start_servers     - the number of children created on startup.
;                                    this value must not be less than min_spare_servers 
;                                    and not greater than max_spare_servers.
;
;             pm.min_spare_servers - the minimum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is less than this
;                                    number then some children will be created.
;
;             pm.max_spare_servers - the maximum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is greater than this
;                                    number then some children will be killed.
; Note: This value is mandatory.
@endrureza
Copy link

I am looking for best server configuration which can handle around 10000 real time traffic or any recommendation.

yeah, as for me i wouldn't tweak this setting too far in order to reach high traffic. i would consider using load balancer

@bonyod
Copy link

bonyod commented Feb 14, 2020

Hi, I have 8GB RAM and 2vCPU (m5.large AWS) any idea to maximize server performance? Avg pool size is : 32MB
I have use these settings:
pm.max_children = 192
pm.start_servers = 100
pm.min_spare_servers = 100
pm.max_spare_servers = 175
pm.max_request = 2000
is this ok?

@abdennour
Copy link

Guys! you must make everything auto/dynamic if you are running on top of Kubernetes cluster. When CPU or Memory reaches the thresholds, k8s HPA will do the work.
So now the question: how to make everything dynamic and open ?
Even nginx, I want to configure it like this :

worker_processes auto;
events {
  worker_connections  ??;
  multi_accept on;
  use epoll;
}

@Herz3h
Copy link

Herz3h commented Oct 20, 2020

Any reason you put php-fpm7.0 in process name instead of php-fpm for the Determine system RAM and average pool size memory.
part ?

@mubasshir
Copy link

@bonyod whats your final config?

@bonyod
Copy link

bonyod commented Nov 9, 2020

@bonyod whats your final config?

pm.max_children = 50
pm.start_servers = 12
pm.min_spare_servers = 5
pm.max_spare_servers = 25
pm.max_request = 0

But still not at best performance.

@pultho
Copy link

pultho commented Nov 9, 2020

@bonyod the prop is called pm.max_requests not pm.max_request 👀

When setting it to zero you're going to run into memory issues if garbage collection of PHP or some framework isn't working properly. You can set the number quite high to 20 - 50k requests if your app is performing well with memory but zero isn't recommended.

@mubasshir
Copy link

@pultho what should be the ideal config for m5.large?

@dwaqaddi
Copy link

dwaqaddi commented Apr 27, 2021

Hi @holmberd,

How did you came up with the values for the following?

pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

Is it safe to calculate it this way?

pm.start_servers = No. of cpu cores x 4
pm.min_spare_servers = No. of cpu cores x 2
pm.max_spare_servers = No. of cpu cores x 4

I have a t3.small server which has 2 cpus and 2 gb ram, is it okay to use the setting below with 'dynamic'?

Average Process = 70mb
RAM = 1900mb

pm.max_children = 27
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_request = 1000

@thanksmia
Copy link

Hi, i did sudo nano on /etc/php/7.4/fpm/pool.d/www.conf

But the problem is I still get the same error log after increasing children to 17 i still get : WARNING: [pool www] server reached pm.max_children setting (5), consider raising it

Help!!

@holmberd
Copy link
Author

holmberd commented Aug 5, 2021

@thanksmia I suggest you use a more appropriate channel to ask for help, e.g. https://stackoverflow.com

@nabtron
Copy link

nabtron commented Feb 14, 2022

@thanksmia this might be because your server is creating individual files for each virtual server / domain that you add. You need to check other files in the same folder of pool.d named as random numbers, and find the one that is for your server (it has the name of your server account on top of each file) and edit it as explained here: https://socalledhacker.com/index.php/2022/02/14/error-fpm-initialization-failed-solved/

@CRC-Mismatch
Copy link

CRC-Mismatch commented Jun 7, 2023

@abdennour I'm not sure you'd really want to set anything to "auto", since Kubernetes doesn't "replace" the presented values for available CPU cores or RAM size for each pod, it only applies its limits and that's it; if you run free -h or check for the number of CPU cores inside a pod, you'll see that the reported numbers are for the actual node this pod is running inside of. Setting everything to "auto" will only lead to a scenario where your HPA scales everything, but your ingress doesn't know that those pods are already over their limit, leading to a snowball effect inside each pod, leading to OOM kills and broken pipes for that pod while PHP-FPM restarts or tries to respawn dead workers that have no mCPUs or RAM available to work with (and the HPA starts going crazy, scaling to the max since from its POV, the scaling isn't solving the excessive resource consumption for some of the pods)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment