Since WordPress is one of the most popular hosting platforms in the world, we have a significant amount of customers who use and trust WordPress for their websites. Throughout the years, we've spent a considerable amount of time working with the platform from a server perspective to optimise, tune and ensure that we offer a great WordPress environment. What we haven't seen completed recently was a comparison as to what effect plugins have to performance, as well as various PHP versions. So, we've written this article so that we have some reliable performance metrics to measure the effect of adding plugins, PHP versions and what effect caching has on performance.
The speed of your website is a critical component of the success of your website. Fast sites lead to better user experience and in turn gives greater confidence in your business or company. If you're running an eCommerce site, the statistics are even harder to ignore. According to KISSmetrics 40% of consumers will abandon a cart for a website which takes longer than 3 seconds to load. Nearly 80% who have experienced performance issues with a website are less likely to buy from the same shop again. There's also the SEO component too, Google uses the speed of the site as one of the factors for ranking your website.
If you ignore your website performance then your competitors will get the upper hand.
For this testing, we’ll be using a minimal CentOS 6 (64 bit) build using our container based hosting. We’ve ensured that the resource allocation is dedicated to ensure repeatable performance during testing. Unless otherwise specified below, we’ll be using stock configurations.
Note: The premise of the testing is aimed at smaller sites with less than 10,000 hits a day, since this is where many WordPress users start to run into issues. We've aimed the specs on what we see for many "typical" small and medium-sized enterprise (SME) based systems. Of course, if we were talking about high end sites then the testing, environment used and optimisation techniques would be quite different. We've recently provided WordPress infrastructure platform which sustains over 1Gb/s of traffic, so it's all about the right deployment for the right environment.
This base configuration includes
- MySQL 5.1
- PHP 5.3.3
- Apache 2.2.15
This is running on a VPS with 1GB of RAM and 2 CPU's allocated (E5 based Xeons).
We then quickly install WordPress 4.0 by downloading the zip from the WordPress site and running through a standard configuration. I won’t document how to do that for this article, if you want instructions on how to install it manually you can read the guide here.
The only item we changed from the standard configuration was “AllowOverrides” within the html directory so that the mod_rewrite rules could be set in the .htaccess file.
For a clean build, we now have a basic reference to run. All tests are repeated three times to ensure consistency. We’re simply using the Apache Benchmark tool, which solely focuses on the performance of the server and application and not necessarily what occurs in real world performance. It will give us the Time To First Byte (TTFB), which is only one part which needs to be considered when looking at overall website performance. What it does give is a good indication as to how the server and server code performs, so it's the main focus of this article.
We're using the same test for each step, which is to use one concurrent thread to make 50 requests to the main WordPress page. This is a very low workload but will give a reasonable and repeatable metric to measure the performance. These tests are being run from a different VPS on the system server, so that network performance isn't a factor.
ab -n 50 -c 1 http://wpserver/wordpress/
The output looks like this:
ab -n 50 -c 1 http://wpserver/wordpress/
This is ApacheBench, Version 2.3 <Revision:655654>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking wpserver (be patient)…..done
Server Software: Apache/2.2.15
Server Hostname: wpserver
Server Port: 80
Document Path: /wordpress/
Document Length: 7716 bytes
Concurrency Level: 1
Time taken for tests: 15.253 seconds
Complete requests: 50
Failed requests: 0
Write errors: 0
Total transferred: 398250 bytes
HTML transferred: 385800 bytes
Requests per second: 3.28 [#/sec] (mean)
Time per request: 305.059 [ms] (mean)
Time per request: 305.059 [ms] (mean, across all concurrent requests)
Transfer rate: 25.50 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 273 305 15.2 299 349
Waiting: 273 305 15.2 299 349
Total: 273 305 15.2 299 349
Percentage of the requests served within a certain time (ms)
100% 349 (longest request)
This gives us our mean starting value of 305ms for the server response time. Not too bad, but certainly far from perfect if we want to provide the best customer experience and allow the website to scale.
So, lets do what most WordPress users do and install a few plugins. I must make this extremely clear: We don’t consider these plugins bad, nor should you avoid using them. Extra functionality can create further overhead, so it’s simply something you need to consider when installing plugins. This testing is simply to help quantify the difference and how to mitigate any drop in performance.
The first is the Wordpress SEO Plugin by Yoast. All we enabled was the permalinks, which is what is typically used. The mean response is now 375ms.
Next, we’ve added Contact Form 7 (without doing anything but enabling the plugin) and the mean response time has now inceased to 401ms.
Installing Jetpack brings this up to 441ms. You can see that each plugin adds a small, but measurable performance overhead.
Now lets add a full e-Commerce solution to our site, using wooCommerce. This now brings our mean time up to 595ms.
Just to confirm that it’s not external factors and to validate the results, I then disabled these additional plugins and re-ran the testing. The mean response dropped back down to 301ms, which is virtually the same value we started with.
Again, there’s nothing wrong with any of these plugins. This build is what I see many typical small business websites, so it’s nothing out of the ordinary. What must be noted is that these plugins effectively doubled the time the server takes to render a page. This means we need to look at what we can do to optimise and speed up our WordPress installation.
Upgrade PHP / MySQL
The first steps are to see what impact running the latest variants of PHP and MySQL do, since this is something you should do from a “best practices” perspective anyway. As we’re an official mirror for the Remi repository, this is the method we’re using.
Lets upgrade PHP to PHP 5.4:
yum upgrade php
This will also upgrade MySQL to version 5.5 (5.1 is stock), since it’s a dependency of the PHP 5.4 build for the Remi repo.
Then, restart the MySQL server and Apache and upgrade the MySQL database:
service httpd restart service mysqld restart mysql_upgrade
What difference did this make? Our mean is now 593ms (with the plugins enabled), basically no change.
Rattling through the tests, I then upgraded to PHP 5.5, restarted Apache and re-ran the test (3 times of course). Result? 579ms. A little bit better, but not enough to be statistically significant. The reality is this wouldn’t be noticed by the user and certainly won’t increase the amount of users the server can handle concurrently.
Since we now have PHP 5.6.0 released as a stable build, let’s give it a go. The result? A mean of 576ms. Not a notable improvement here. This isn’t to say that running the latest PHP isn’t worth doing, just don’t expect that it’s going to instantly boost your performance. There are other advantages to running newer versions of PHP, especially when it comes to updates and security.
A basic install of WordPress isn't overly database intensive, but what’s the effect of a bit of basic tuning? We can use MySQL Tuner as reference to go forth with, but before making changes you should ensure you read our MySQL Tuning Guide.
The first main item to look at is query caching. We enable it by adding the following field into /etc/my.conf:
This gives the server a modest amount of memory in which to cache lookups. We restarted MySQL and re-ran the testing, which resulted in a mean of 568ms. Again, no huge performance gain. Let’s enable all of the suggestions, so the extra parts to our my.conf file look like this:
query_cache_size=8M tmp_table_size=16M max_heap_table_size=32M thread_cache_size=4 table_open_cache=800
Result: 571ms. Clearly, MySQL isn't a limiting factor for these tests. To confirm our results, I even disabled all the plugins temporarily to see if the result is the same as our starting reference. This brought the mean average back down to 297ms, so again perfectly consistent with the base results.
Conclusion: MySQL gives you pretty good performance right out of the box. The performance difference between PHP 5.4 / 5.5 and 5.6 isn’t significant for WordPress.
A lot of this tuning will assist with a site which is heavily loaded, especially with a number of widgets displayed or shopping carts. The age old ethos of avoiding “premature optimisation is the root of all evil” sings strong and loud here.
If simply running the latest software and a bit of tuning of MySQL hasn’t given us performance gains, what else can be done then? The answer is caching. WordPress have a guide on this here, with their top recommendation being W3 Total Cache. Here at Conetix, this has always remained our answer to those having WordPress performance issues, but there's one option to benchmark first. PHP 5.5 and above now have the OPcache library, which stores the pre-compiled bytecode in memory. Without this, every time you call a PHP based site it has to compile the PHP code into machine code before executing. OPCache stores this result in memory, which therefore reduces the overhead every time you call a PHP script.
Firstly, lets install and enable the PHP OPcache:
yum install php-opcache service httpd restart
So does it make much of a difference? We now have a mean time of 151ms, with the plugins enabled. That’s a response time decrease of nearly 75%, which will not only be noticed by your clients by also increase your server capacity. This is the sort of optimisation we need to achieve!
Running against the WordPress server with all the plugins off again drops this down to 69ms, which is again about a 75% decrease against the stock figures. This is a great improvement and therefore we highly recommend using PHP 5.5+ with OPcache enabled. It can be installed on previous versions via PECL as well, but it's a much easier task to simply upgrade to PHP 5.5.
Is this all we can achieve? Of course not! W3 Total Cache takes this caching a step further and covers areas such as object and page caching. After installing W3 Total Cache, I enabled the Object Cache to see if this makes any difference. Result? 190ms. Those who are following the figures carefully will note that this is slower. The reasonable conclusion to draw from this is that the PHP OPCache is more efficient at optimisation then just at the object level.
Now lets try the Page Cache. This stores a complete compiled version of the whole page, rather than having to run the database queries and compile the templates and plugins each time. The result? 2.9ms. There’s no typo here, that’s 2.9ms! Clearly, this has provided the most significant performance gain yet. Not only will the user experience dramatically increase, but the resource drain on the server will also significantly decrease.
Conclusion: Installing W3 Total Cache and enabling the Page Cache gives a 99% decrease in server response times. The difference is literally that black and white.
There’s a few caveats with caching of course, it needs to be tightly coupled to your platform in order for changes to become live. In the case of WordPress, if you're modifying data outside of the framework (not recommended anyway!), W3 Total Cache won't be aware of the change. As long as you stick to a well planned system then this shouldn't be a problem.
The results are pretty clear, we took a very basic WordPress instance (including commonly used plugins) and improved the server response from nearly 600ms down to 3ms, a 99% decrease in response times. While this may only be for a test site, similar results should be possible from your website as well. As a picture says a thousands words, here's a graph of the results:
The effect of adding various plugins, PHP version changes and caching can be quite clearly seen. The real world experience is noticeable as well, so the performance increase extends beyond a few basic benchmarks.
So, as our takeaway points for this article:
- Variations in the PHP versions don't provide any performance gains for lower traffic sites.
- Plugins can slow down your website, but this doesn't make them a bad thing.
- OpCache makes a big difference to performance.
- W3 Total Cache makes the biggest difference and is the largest contributing factor to performance on your WordPress based site.
- Optimisations beyond the server level are needed to make your website perform optimally.
Again, I want to re-iterate that these apply to SME level deployments of WordPress only. If you're looking at optimising your WordPress based installation for hundreds of thousands of users, the level of optimisation and work required to sustain this requires a completely different approach. This is something we have experience with too and we may look to detail how we've achieved this for some of our clients in a future article.
If you have any questions or other suggestions, please feel free to add them below!