Tuning PHP FPM on Nginx
As the Store Locator Plus® SaaS platform grows, we find it more important than ever to fine-tune our web server and PHP processes to serve the more critical data and network demands better. A recent performance review showed process timeouts during large data imports and side-loading, especially when the read and write endpoints hit the same server node. Here are some things we did to improve performance.
1080 words, 4 min 19 sec read
Get off faux sockets.
PHP FPM is typically installed with file-based sockets. While this lessens the traffic on the network hardware, most modern servers are equipped with fiber-ready network connections. These network ports and the TCP stack that interfaces with them can often handle a higher peak load of I/O requests than the file system can manage via the “pretend” sockets run through the operating system file I/O requests.
If your server runs on solid-state drives, there may be less disparity between the I/O rate of a network stack and a file stack. We use high-end SSD drives and high-speed network cards on the servers — yet we still found we could push through nearly twice as many requests to PHP-FPM from nginx when switching to TCP sockets.
Configure PHP FPM for TCP sockets
You’ll need to configure your PHP FPM to listen on 127.0.0.1:9000 — the network loopback address port 9000. It is a good idea to set the only client to be yourself as well.
;listen = /run/php/php7.0-fpm.sock
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
Change nginx fastcgi params.
Now go tell Nginx to talk to PHP-FPM on the new sockets. You’ll need to do this for every site, snippet, or other included config file that directs PHP traffic.
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# default: faux sockets via Unix file
#fastcgi_pass unix:/run/php/php7.0-fpm.sock;
# modified: actual TCP socket
fastcgi_pass 127.0.0.1:9000;
}
This article on servers for hackers will give you additional insight.
Look At PHP FPM Memory Consumption
Use a command like htop or ps to review memory consumption. For HTOP, the values include VIRT – the total memory available to a process, RES – the resident memory or memory used by the process, and SHR – the amount of memory that may be coming from shared processes.
htop
You typically want to look at RES as the amount of memory each process uses. Average it out. BUT you must know how your PHP and web process libraries are configured and the shared memory stack on your server. Most libraries in PHP are shared. That means a bulk of the code, which can be as much as 80% of the shared library memory, is only loaded ONCE, no matter how many PHP processes you activate.
Our setup averages 139M on resident memory and 123M on shared memory. That makes sense, as most of our web processes use the same PHP libraries and a massive chunk of identical PHP code. A data stack of 16M per PHP process is reasonable.
pmap
You can validate this by using the pmap command with the process id:
# sudo pmap 2963
This returns the entire memory map of process #2963
In the example below, 899704K of total memory is in use, but a large chunk is system libs, PHP libs, and web server lib shared code.
[SEE PIC AT THE TOP OF THIS PAGE]
The visibility that pmap provides may indicate libraries or features you may have enabled and can disable. We found a production server with xdebug libraries still active. Turning that off cut nearly 50M or resident memory from every process!
free -m
Looking at the system memory with free-m gives you a high-level overview of total system memory usage. It will report the total memory, used at the moment, free, shared memory, and buffers.
You will want to track buffers and memory used by non-PHP processes if you run other apps on your server, such as the database. Our web servers only serve web apps, so there is almost no additional overhead. That means I can use the buffer value in calculating how many PHP processes to spin up.
Calculate PHP Max Processes
The simple version of the formula:
Total system ram – used by apps ram – buffer ram/ram use per PHP app
16GB – 1GB (various system processes) – 500M (cache process) – 500M (php) = 14GB for PHP apps / 16M = about 800 max processes
In our example server from the cluster, a web-app-specific node, there is 16GB available, of which various server processes consume 1GB, 500MB of high-speed local cache, and another 500M is used by PHP and related shared code. That leaves 14G for PHP apps averaging 16M/process. Each node can handle around 800 simultaneous web requests or PHP-FPM children
PHP FPM Pool Parameters
Tuning the PHP configuration file is also essential. Here we are referencing PHP 7.4 and the FPM service on Ubuntu. The configuration file we are interested in lives at /etc/php/7.4/fpm/poold/www.conf
pm.max_children
Per the calculations above, this should be set based on the total available memory. We are now running on a server with 8GiB RAM , 1 GiB of which is allocated to system overhead and the main PHP engine itself. That leaves 7GiB for PHP application RAM. Our app now consumes 300MB per process.
Total RAM – System Overhead = 7G / 300M = 23.3 children max, so we’ll set that at 20.
pm.start_servers
Some online resources recommend this to be CPU cores x 4; however, we could not set it to more than the # of CPU cores.
pm.min_spare_servers
Some online resources recommend this to be CPU cores x 2; however, we could not set it to more than the # of CPU cores.
Reindexing in the database
Keep in mind that your PHP processes do not run in a vacuum. Most PHP apps running on web servers will talk to a database. Spinning up 800 PHP connections will likely need 800 database connections, even when using persistent connections. Each web session will demand its channel for most apps.
Make sure your database server is configured to handle all those connections. We run on Amazon Aurora database clusters, varying wildly in how many links they can drive. Make sure the max_connections on the database engine match how many you may throw at it.
Related Articles
Related
Exploring Potential Quantum Properties of Brain Electromagnetic Circuits within the Limbic System
24 min read:
Steve M. Garman, AS, BS, MA, MD
-This paper posits a novel theory proposing that electromagnetic fields in the brain, known as brain waves, may exhibit quantum properties and that these fields could potentially guide and accelerate entangled particles along curvilinear tracts.
Intel’s Tunnel Falls Quantum Chip: A Comparative Report
2 min read:
-Quantum computing has been a rapidly evolving field, with various companies and research institutions developing their own quantum processors, also known as quantum processing units (QPUs). 1
Intel recently announced the release of its newest quantum research chip, Tunnel Falls, a 12-qubit silicon chip. 2