We don’t focus on LAMP packages like WordPress or Drupal, but sometimes we pick them up in order to work with particular design partners. While the packages are generally optimized to allow deployment on shared hosting, factors from client preference to site traffic often drive our installations to VPS hosting, where the software infrastructure is not necessarily tuned to handle them. We’ve assembled a suite of tools to help us optimize the LAMP stack on a VPS.
These scripts and steps were developed tuning an Ubuntu 10.4 LTS (“lucid”) system installed at SliceHost. Generally there are two concerns: memory use (because these tools will use as much memory as they’re given, and MySQL will often throw a tantrum if it doesn’t get what it wants) and site speed.
Apache
The default Apache install slurps quite a lot of memory. The main culprit is the MPM configuration, which is where Apache decides how many instances to keep active and how much work they should each do before they shut down: basically controlling Apache’s process spawn rate. Default installations often have too many workers open by default, and spawn more too easily, thus using more memory than is really needed.
The block in /etc/apache2/apache2.conf where this is configured looks like this:
<IfModule mpm_prefork_module>
StartServers 1
MinSpareServers 1
MaxSpareServers 2
MaxClients 20
MaxRequestsPerChild 4000
</IfModule>
The default numbers are generally much higher; this block has been tuned. However, don’t swallow these numbers either; instead, figure your own. MinSpareServers is how many processes are sitting idle; a higher number may improve site response time, but too high a number will let Apache use more memory than it needs. MaxSpareServers caps this number.
MaxClients tells Apache when to give up because it’s about to run out of memory. To figure a good setting for this, we use a script from the great folks at RimuHosting:
#!/bin/bash
echo "This is intended as a guideline only!"
if [ -e /etc/debian_version ]; then
APACHE="apache2"
elif [ -e /etc/redhat-release ]; then
APACHE="httpd"
fi
RSS=`ps -aylC $APACHE |grep "$APACHE" |awk '{print $8'} |sort -n |tail -n 1`
RSS=`expr $RSS / 1024`
echo "Stopping $APACHE to calculate free memory"
/etc/init.d/$APACHE stop &> /dev/null
MEM=`free -m |head -n 2 |tail -n 1 |awk '{free=($4); print free}'`
echo "Starting $APACHE again"
/etc/init.d/$APACHE start
echo "MaxClients should be around" `expr $MEM / $RSS`
MySQL
The best tool for tuning MySQL is the MySQL Performance Primer script. Download that to your home directory on the server being tuned and chmod 755 tuning-primer.sh to make it executable. You should also run which bc to see if the bc calculation language is installed; if it isn’t, try sudo apt-get install bc to get it.
This script prefers to have at least 48 hours of continuously-running server to work with. If you let it, it will produce a my.cnf configuration file with a number of suggested directive changes, generally pointed at optimizing your memory usage and MySQL performance. It’s pretty impressive.
If you’re serious about tuning your application to get fast results from MySQL, enable the Slow Query Log while you’re at it, but don’t expect this to be too helpful with packages like WordPress or Drupal, which don’t really let you get at the query builders directly.
PHP
The best thing to speed up PHP is the APC or Alternative PHP Cache. This caches PHP’s “opcodes”, the compiled versions of the PHP scripts, so they won’t be recompiled with each request.
This is a good primer for the installation on Ubuntu. One catch is that the initial APC install (the sudo pecl install apc part) often throws an error. If it fails, try sudo pecl install apc-beta and see if that works better.
Definitely install the cache status page somewhere when you’re done. It provides some interesting data about how the cache is speeding things up.