PHP is one of the most popular server-side scripting languages used for web development. It powers millions of websites across the internet, including WordPress, Drupal, Magento and many more.
However, PHP is not inherently optimized for high performance and scalability out of the box. This is where PHP-FPM comes in.
PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation focused on performance. It is the preferred method of running PHP for high traffic websites and web applications.
In this comprehensive guide, we will dive into how to optimize PHP-FPM for maximum performance and scalability.
What is PHP-FPM and How Does it Work?
To understand how to optimize PHP-FPM, we first need to understand what it is and how it works under the hood.
PHP-FPM is a daemon process manager that handles PHP requests independently from the web server. It manages multiple PHP worker processes and recycles them between requests for better performance.
Here is a high-level overview of what happens when a request comes in:
-
The web server (e.g. Nginx) receives the request from the client.
-
Nginx passes the request to PHP-FPM via a FastCGI protocol.
-
PHP-FPM initializes a PHP worker process from its process pool to handle the request.
-
The PHP script is executed by the worker process.
-
Output is passed back to Nginx via FastCGI.
-
Nginx sends the response back to the client.
-
Once finished, the PHP worker process is returned back to the pool for reuse.
This is more efficient than the older mod_php approach, where PHP is embedded in the web server process and cannot be managed independently.
Some key advantages of PHP-FPM include:
-
Better process management – The PHP worker pool can be fine-tuned for optimal performance.
-
Memory savings – PHP processes are recycled instead of restarted per request. This saves memory especially for long-running processes.
-
Increased throughput – More requests can be handled simultaneously since PHP execution is separate from the web server.
-
Improved stability – If PHP crashes, the web server can continue to serve other PHP-FPM pools or static files.
Understanding how PHP-FPM operates sets the foundation for tuning it for maximum performance.
PHP-FPM Configuration and Optimization
The main PHP-FPM configuration file is usually /etc/php-fpm.conf or /etc/php-fpm.d/www.conf on Linux systems. This controls global settings and the configuration for each pool.
Here are the key things we can optimize:
1. Tune pm (Process Manager) Settings
The pm settings control how the PHP-FPM worker processes are managed:
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm – Set this to dynamic which is ideal for most scenarios. ondemand can also be used for low traffic sites.
pm.max_children – Maximum number of worker processes that can be open simultaneously. Set this appropriately high based on your traffic load.
pm.start_servers – Number of processes launched at startup. Can be set to a low value since the process pool expands dynamically per load.
pm.min_spare_servers – Minimum number of idle processes maintained in the pool. Avoid setting this too high.
pm.max_spare_servers – Maximum number of idle processes before exceeding ones are killed. Tweak together with the above settings to optimize idle process count.
Tuning these values allow PHP-FPM to scale up and down smoothly while making efficient use of system resources.
2. Adjust pm.max_requests
The pm.max_requests setting specifies how many requests a worker process should handle before being recycled:
pm.max_requests = 500
A value between 500-1000 is good depending on your typical request execution time. Recycling workers regularly helps prevent memory leaks.
You can set this to 0 to disable automatic recycling, but this is not recommended. Make sure to tune this based on your application behavior.
3. Increase pm.status_path Requests Limit
The pm.status_path exposes a URL to monitor the status of PHP-FPM pools (/status). For example:
pm.status_path = /status
However, this path is limited to only handling a few requests per second by default. Increase its request handling capacity by setting:
pm.max_children = 50
pm.max_requests = 500
This allows more parallel monitoring requests to the status page.
4. Tweak php.ini Settings
Many PHP performance optimizations can be made by tweaking php.ini values:
- Increase
memory_limitbased on your application needs. - Adjust
max_execution_timeto allow longer running processes if required. - Reduce
realpath_cache_sizeandrealpath_cache_ttlif dealing with a large number of file paths. - Increase
opcachesettings likeopcache.memory_consumptionfor better opcode caching.
Experiment with tuning these based on your specific PHP application‘s behavior.
5. Enable Opcode Caching
Enabling opcode caching via OPcache greatly speeds up PHP execution:
opcache.enable=1
Other useful OPcache settings to configure include:
opcache.memory_consumption– Increase for better hit rate.opcache.interned_strings_buffer– Set to 16-64 MB to store strings in shared memory.opcache.max_accelerated_files– Bump up from default 4000 limit if required.opcache.validate_timestamps– Set to 0 to disable costly file timestamp checks.
Tweaking OPcache is one of the most effective ways to boost PHP-FPM performance.
6. Preload PHP Scripts
OPcache provides the ability to preload PHP scripts on startup:
opcache.preload=/path/to/app
This precompiles your application code on bootup for much faster execution during requests.
7. Improve Logging Configuration
It‘s important to set up effective logging to monitor PHP-FPM health:
access.log = /var/log/php-fpm/access.log
slowlog = /var/log/php-fpm/slow.log
Access logs record all requests while slow logs catch any slow executions exceeding a threshold:
; log slow requests taking longer than 60 seconds
request_slowlog_timeout = 60s
Proper logging enables identifying and troubleshooting any PHP-FPM bottlenecks or issues.
Advanced PHP-FPM Optimization Tips
Here are some additional optimizations for pushing PHP-FPM performance further:
-
Run multiple PHP-FPM pools with different
pmconfigs on multicore boxes to isolate requests across CPU cores. -
Enable APCu caching to store common objects in memory instead of rediscovering them on each request.
-
Pre-resolve paths used in scripts via
realpath_cache_*to avoid extra filesystem lookups. -
Separate out static assets to be served directly by the web server instead of going via PHP.
-
Cache database query results in Redis/Memcached to reduce database trips.
-
Use asynchronous PHP workers like ReactPHP to speed up queued jobs/tasks handling.
-
Distribute load across multiple PHP-FPM boxes via Load Balancing.
-
Enable PHP Zend Thread Safety and parallel processing if supported by your application.
-
Limit segments of code execution time with
set_time_limit()to prevent one slow section from blocking others. -
Profile code with Xdebug/Blackfire and optimize bottlenecks in the application logic itself.
-
Use opcode compilers like Phalanger or HipHop VM for increased execution performance of PHP code.
-
Shift from PHP to Go, Elixir, Rust or other high-performance languages where possible.
As you can see, optimizing PHP-FPM opens up many possibilities for pushing PHP performance to the limits.
Measuring PHP-FPM Performance Improvements
It‘s critical to measure before and after metrics when optimizing PHP-FPM to validate the impact of changes:
Benchmark Tools
- Apache Bench – Basic load testing tool for generating requests.
- JMeter – Open source load and performance testing app.
- BlazeMeter – Enterprise grade performance testing platform.
Metrics to Monitor
- Requests per second
- Latency per request
- Error rates
- Memory usage
- CPU usage
Monitoring PHP-FPM
- Check
/statuspage provided by PHP-FPM for pool stats. - Logs – Monitor access logs and slow logs for anomalies.
- New Relic – Application monitoring agent with PHP support.
- Blackfire – Detailed profiler to identify PHP bottlenecks.
Continuously measuring key performance metrics is vital to ensure optimizations deliver expected benefits.
Conclusion
Optimizing PHP-FPM provides a powerful method to achieve blazing fast PHP performance and scale websites.
Follow the tips outlined in this guide to get started tuning your PHP-FPM config. Try out different settings across live traffic and benchmarks to validate improvements.
With careful tuning, you can squeeze out every last bit of performance from your PHP application and infrastructure. The end result is a highly optimized PHP environment capable of delivering lightning fast response times and handling heavy request loads.