I recently wrote about the impact that setting how PHP-FPM’s process manager controls child processes from dynamic (pm = dynamic) to ondemand (pm = ondemand) has on RAM usage. You may read the article at How to reduce PHP-FPM (php5-fpm) RAM usage by about 50%.
One other interesting PHP-FPM setting I got to learn a little bit more about while I was building that server is listen.backlog. The default value on Linux is 65535, but the comment in the default PHP-FPM pool file (/etc/php5/fpm/pool.d/www.conf) on Ubuntu 14.04 says the default on FreeBSD and OpenBSD is -1, with no explanation what the difference is.
The man page for listen defines the backlog argument as the:
the maximum length to which the queue of pending connections for sockfd may grow. If a connection request arrives when the queue is full, the client may receive an error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the request may be ignored so that a later reattempt at connection succeeds.
That’s not the type of information most people get to read when setting up PHP-FPM, but it’s one I had to by accident. On the server I was building, I made the decision to change the value to match the default on FreeBSD and OpenBSD after also changing how the process manager controls child processes.
Then when I ran php5-fpm -tt to test the settings, I got a warning at the top of the output:
WARNING: [pool containerapps.net] listen.backlog(-1) was too low for the ondemand process manager. I updated it for you to 65535. NOTICE: [General] NOTICE: pid = /var/run/php5-fpm.pid
So -1 is too low, but 65535 is fine. That got me thinking: What’s the optimal value for the process manager’s listen.backlog setting? Most sources I found didn’t really help much, but coming across The meaning of listen(2)’s backlog parameter (Chris Siebenmann) and Oracle, Listener, TCP/IP and Performance (Robert Milkowski) were my rewards for the search effort.
So what did I learn about listen.backlog in general and specifically on Linux? This quote from Chris Siebenmann’s article sums it up:
Note that most Unixes silently impose a maximum value on the backlog value. Some impose a minimum as well, and some impose different minimums depending on what the socket protocol is.
This leads to the obvious question: what should you set the backlog value to when you call listen()? My current view is that setting it low doesn’t reliably do anything so you probably should set it high. Given that the kernel will clamp the value if you go too high I suggest going for at least 128 or 256, maybe more; going high in your software means that the actual number is up to whatever limit the local system has set.
There you have it. The sweet spot, assuming Chris is right, lies somewhere between -1 and 65535, but much, much lower than the default on Linux. By the way, setting it to -1 means there’s no limit.
A signed 16-bit integer of -1 has the same binary representation as an unsigned integer of 65535. I guess when they used -1 they meant 65535, or the maximum size possible (if it is bigger than 16-bit), but PHP-FPM is taking the sign literally.
-1 means unlimited so it is higher than 65k so why does it complain that it is too low?