Some useful performance optimization tips for optimizing Apache, PHP FPM, and APC for Amazon EC2. In this case the configuration examples are the settings that work best for our Small instances, but certainly these concepts will apply to other instance types as well.
Optimizing your environment can be quite time consuming and overwhelming since there are an overwhelming amount of configuration options, a number of supplementary packages to evaluate, and a lot of trial and error to determine which knobs and dials provide the most bang for your buck with your environment. Here are the variables and settings we found the most useful to focus on:
Since Small instances only include one CPU, turning on KeepAlives seems to be a good idea. You’ll also want to adjust the “MaxClients” prefork setting, which seems to be the most important of these. Ours is set to 75, but it doesn’t seem that the defaults are a horrible mismatch, so you may not find that tweaking these makes a lot of difference. Enabling the deflate module works fine, and you can lower the “Timeout” value if you don’t want to do business for the default 300 seconds (our is set to 30 seconds).
Figure out where the FPM log file resides, and learn to monitor it for notices about the pool being busy, timeout values being hit, etc. This will sort of give you a “hot and cold” sense as to how the following settings are working. In Debian be sure that you edit any corresponding php.ini configuration options for FPM (/etc/php5/fpm) and not for Apache (i.e. PHP running as an Apache module), CGI, or CLI.
- pm.start_servers = 4
- pm.min_spare_servers = 4
- pm.max_spare_servers = 20
- pm.process_idle_timeout = 5s
- pm.max_requests = 100
Monitor your RAM consumption and lower these values to ensure that as memory balloons that you do not have to use swap space. The max_requests setting is particularly helpful since it helps prevent memory ballooning from leaky PHP scripts. If you use a service like Monit you can make use of the “ping.path” argument to help monitor FPM and auto-restart it when it becomes unresponsive. You can also enable the slow log (“request_slowlog_timeout”, “slowlog”) if you wish to profile certain sites or certain PHP scripts.
Last but not least, refining APC was by far the most beneficial to dropping load averages from as high as 20 to consistently below 1. For whatever reason, while the PHP-FPM default settings were too high for our environment, the “apc.shm_size” default setting in particular seems ridiculously low, and perhaps should be increased as to be more useful. To determine how well APC is working for you, you should track down an “apc.php” file which provides a handy stats page showing how many requests have been served via memory (i.e. are taking advantage of APC memory cache). For whatever reason this file is not included in the Debian package, so I compiled the APC package and copied the file to my server:
cd APC-3.1.9 phpize ./configure --with-php-config=/opt/local/bin/php-config scp apc.php yourserver:
These instructions are for OS X and Macports, you’ll have to modify the path to php-config and/or phpize to suit your environment. If you are seeing tons of fragmentation and APC not being fully utilized being displayed on apc.php, increase the “apc.shm_size” value from its default 32M to something like 256M. Note that in Debian this path is “/etc/php5/fpm/conf.d/apc.ini” – again, there are separate config files for each of Apache (i.e. PHP running as an Apache module), CGI, CLI, and FPM.