This article of mine has been original published on Wazi
WordPress, the popular content managing system (CMS), is easy to set up and use, and well supported by both its community and professional consultants. WordPress depends upon a complete stack that comprises an operating system, database, web server, and PHP. If you can optimize this stack, you can enhance the performance of your site. Here are some tricks and best practices for a setup that will improve your throughput without forcing you to upgrade your hardware.
Let’s start with a look at the Linux operating system, MySQL database, and nginx web server. Later we’ll get to PHP, some setup and plugin work with WordPress itself, and Varnish Cache, a web application accelerator.
In theory you could run WordPress on a Windows server using software like EasyPHP, a package that allow you to take advantage of all the power and flexibility that the dynamic PHP language offers with Windows. The package includes an Apache server, a MySQL database, phpMyAdmin, and development tools for websites and applications.
But for its better license, performance, and optimization capabilities, we’ll go with GNU/Linux, and in particular with CentOS 6. It’s a stable and free Linux distribution based on Red Hat Enterprise 6, so all the packages and commands work exactly the way they do on RHEL 6. If you prefer another distribution, such as Debian or Arch, you’ll have some files located in paths slightly different or packages with different names or version, but the concepts here are applicable on any GNU/Linux distribution.
Regarding CentOS 6 optimization, and in general for any GNU/Linux distribution, I have three tips:
- If the server (real or virtual) where you are installing CentOS 6 has more than 3GB of RAM, install a 64-bit system; otherwise, choose the 32-bit version – this will save you some RAM.
- Usually CentOS 6 uses ext4 as its filesystem type. Ext4 is a journaled filesystem, which registers all changes, so if the system crashes it can recover the affected files. By default Linux records file access timestamps, meaning every time a process accesses a file there is a small overhead to write the timestamp. In a busy environment, removing this feature can speed up operations.To remove file access timestamps, edit the /etc/fstab file and add, in the line that refers to your WordPress filesystem, the
noatimeoption after the default options:
/dev/sda7 /srv ext4 defaults,noatime 1 2
- This last tip is true for all the software in the stack, but I’ll write it only here: Be sure to run the latest version of your software. This should be bug-free, and so save you from any known problems.
Under Linux we want to manage all our software stack with yum, so we’ll add the EPEL (Extra Packages for Enterprise Linux) repository to our system. The EPEL repository was developed by the Fedora community to provide extra add-on packages for RHEL, which means it’s compatible with CentOS.
To add EPEL on a 32-bit system, run this command as root from a terminal window:
rpm -ivh http://download.fedora.redhat.com/pub/epel/6/i386/epel-release-6-5.noarch.rpm
If you have a 64-bit system, run:
rpm -ivh http://download.fedora.redhat.com/pub/epel/6/x86_64/epel-release-6-5.noarch.rpm
When adding extra repositories, keep in mind that many include newer versions of packages that are available through the standard channels. This can cause problems, as packages may be automatically upgraded when you don’t want them to be and cease to function as expected. To mitigate this problem, use yum priority and give to the EPEL repository a lower priority than the official CentOS repository.
Finally, check and update the system with:
yum check-update yum update
The database server is the heart of any CMS system. Because it’s where all the content and setup information is stored, it can get a lot of requests per second, so improving this layer can yield huge benefits.
Begin by installing the latest release of MySQL server with the command
yum install MySQL-server
. A default installation of WordPress 3.2 installs the database tables as MyISAM, so to save some memory you can tell MySQL to skip the loading InnoDB, MySQL’s other default storage engine, which can save up to 100MB of RAM on your server. Now take a look at some of the most important parameters:
The key buffer stores table indexes in memory, allowing for fast lookups and joins. The parameter accept a value that indicates of how much memory allocate for this operation. I’ll suggest a generic value below, but you can adjust it later with MySQLTuner.
Opening tables can be expensive. For example, with MyISAM, MySQL marks MYI header fields to indicate a table is currently in use. You do not want to open too many tables too frequently; it’s better to keep them open for performance. You can achieve this by adjusting the table cache to a size that is large enough to keep most of your tables open. Start with the number I’ve put in the profiles below and tune it with MySQLTuner over time.
MySQL has a query cache that stores results up to a certain size in memory. The cache is handy for quickly returning commonly accessed data when all other forms of caching (including reverse proxies, page cache, and WordPress caches) have not been invoked.
Here are a few example configuration settings for servers of different memory sizes running both MySQL and a web server on the same machine. These are not perfect, but they are good starting points.
For servers with 512MB RAM:
thread_cache_size=50 key_buffer=40M table_cache=384 sort_buffer_size=768K read_buffer_size=512K read_rnd_buffer_size=512K query_cache_limit=2M query_cache_size=16M query_cache_type=1 thread_concurrency=2*CPU skip-innodb
For servers with 1GB RAM:
thread_cache_size=80 key_buffer=150M table_cache=512 sort_buffer_size=1M read_buffer_size=1M read_rnd_buffer_size=768K query_cache_limit=4M query_cache_size=32M query_cache_type=1 thread_concurrency=2*CPU skip-innodb
For servers with 2GB RAM:
thread_cache_size=80 key_buffer=350M table_cache=1024 sort_buffer_size=2M read_buffer_size=2M read_rnd_buffer_size=768K query_cache_limit=4M query_cache_size=64M query_cache_type=1 thread_concurrency=2*CPU skip-innodb
Once WordPress has been up and running for some time you can tweak your settings by running MySQLTuner, a Perl script that analyzes your MySQL performance and, based on the statistics it gathers, gives recommendations about which variables you should adjust to increase performance. With MySQLTuner, you can tune your my.cnf file to tease out the last bit of performance from your MySQL server and make it work more efficiently.