Testing WordPress: the importance of PHP opcode cache

Today we’re doing things slightly differently with a guest post by Peter (, one of our customers. Peter is the developer of WP-FFPC – a WordPress caching plugin.

The why-s

There were some discussions lately at LinkedIn mostly on the topic of choosing a VPS (virtual private server) over a shared hosting provides any benefits. My opinion: a VPS can clearly outnumber a shared host in performance and freedom, but not in pricing. Price can only be matched when the VPS is an unmanaged one, meaning you (or someone you hire) has to take care of all the configurations, the server management, the monitoring – even the operating system install itself.

For most people this looks horrible and finding a cheap but good system operator is a nightmare for anybody. The problem is, that on a shared host you are limited to the system services. There are really few hosting providers how allow switching between web servers, or even switching PHP versions, and what’s worst: you clearly are not allowed to tweak any of the services.

I know there are really few WordPress users who wants – and is able – to fine tune the backend of his install, but there are tiny things which can make incredible difference.

I decided to make a little test to show how little is enough for, in this case a WordPress Network, to brutally gain on performance.
Originally I wanted to show only the power of WP-FFPC, a full page cache plugin written by me. The problem was that I left APC object cache plugin active, so I decided to show the importance of APC instead.

Test setup

  • KVM VPS V1 plan from CheapVPS
  • Ubuntu server 11.10 (kernel 3.0.0-16-server)
  • nginx 1.0.11 (gzip compression enabled at level 1)
  • PHP 5.3.6-13ubuntu3.6 with Suhosin-Patch
  • Percona server (MySQL replacement) 5.5.20
  • opcode cache: APC-3.1.9*
  • WordPress Network 3.3.1, sunrine (domain mapping) enabled
  • WordPress cache enabled
  • APC object cache plugin*
  • WP-FFPC full page cache for APC plugin*

*APC cache was only enabled for the first test.

The page I was testing is a category archive page. It shows 4 special post: all posts includes numerous small pictures, some larger ones, loading jQuery with some extensions. It’s also a domain mapped sub-blog of the site.

I have to add that I have a little trick made on my server config. Normally all sub-site content is server by PHP in a WordPress Network. This was change by my when I added some extra into my nginx setup. If this test had been done with the default WordPress Network setup, I’m fairly sure my result would be pretty awful, please take this into your count.

The address of the tested page:

What is nginx?

nginx is a webserver, similar to apache2 (running behind most of the web pages on the world).
The main differences: nginx is a lot harder to extend (for example, there are no possibilities to use files like .htaccess in apache), but it eats significantly less memory and CPU time in exchange.

What is PHP?

PHP is one of the programming languages WordPress was written in. Traditional programming languages are needed to be compiled, thus they become and exe, or some kind of binary file. PHP instead is compiling all files, all the time on-the-fly -and this requires inmense computing power.

What is PHP-FPM?

The web server can load the PHP compiler in various ways; apache2 server has a built-in module for it, which, unfortunately, can eat up all the possible memory. An other way is to use a “PHP server”, which can than be access with a protocol, named FastCGI. PHP-FPM is a FastCGI server version of the PHP compiler.

What is opcode caching?

PHP Opcode cache can store compiled variables, pages and parts of the code. By default PHP always recompile everything which is really not neccessery at most times. The opcode cache therefore uplifts a lot of uneeded compilation, speeds up the program and saves CPU time.

My load test setup

I’ve used for making a stress test on my server. I have so low traffic on this very server that the stress test should make a clearly visible difference.

Test schedule

The test setup: 20 minutes total runtime split into 5 minute parts. All parts have limited maximum simultaneous users:

Total Runtime = 20 mins:
Max. 16 users 5 minutes
Max. 32 users 5 minutes
Max. 64 users 5 minutes
Max. 128 users 5 minutes

Here is a screenshot of the program schedule interface:

Click to zoom

Users geographical dispersion

I’ve given extra weight to the Dublin traffic since it’s a UK based site and this is where I expect most traffic to come from in a ‘real world’ situation:

Dublin, IE 50% of all users
Tokyo, JP 10% of all users
Portland, US 40% of all users

Here’s a screenshot of the user scenarios setup:

Click to zoom

Load Test Results

Without APC enabled:

Click to zoom

With APC enabled:

Click to zoom

Meanwhile on the server…

These are munin graphs taken from the server while the test were running. There are two highlighted spikes, the first time was with APC on, the second (~1 day later) is without APC cache.

Number of nginx requests/sec

Click to zoom

Traffic on ethernet device

Click to zoom

Server load

Note: Server has 4 CPUs, therefore 4 means the full utilisation.

Click to zoom


CheapVPS performance

The performance and the capacity of the smallest – and probably one of the cheapest KVM based virtual servers – surprised me again. It could handle 100 siumltaneous connections per second without opcode cache! For calculation: if this would keep up for a day, it would result in 8,640,000 hits on that day, which is way over normal site’s traffic. For £14.40 (with taxes!), this is the best buy ever.

The results

Aggregated 5/sec is not really a bad result, but the system could only handle it until limited number if requests/second. With cache enabled the load time went down by 2 seconds, which is really much (more than 40%) and also, I could not reach the limit of the server. For calculation: keeping 220 req/sec hitrate for a date would result 19,008,000 hits per day, and the server is still serving all the content with the same speed.

The munin graphs show another important thing: without cache, the server load can be measured in at lest 3 times multiplied. This also result that the ethernet traffic and the handled nginx requests per second will fall off as well.

Overall conclusion

  • CheapVPS worth every penny
  • PHP opcode cache should be implemented in it by default, without the need if installing additions.
  • Tweaking the backend can bring out immense performance of WordPress

WP-FFPC WordPress caching plugin

WP-FFPC is a full page cache plugin for WordPress. It can use APC or a memcached server as backend. The naming stands for Fast Full Page Cache.

PHP has two extension for communication with a memcached server, named Memcache and Memcached. The plugin can utilize both.


  • Exclude possibility of home, feeds, archives, pages, singles
  • Use APC or memcached as backend
  • 404 caching
  • redirects caching
  • Last Modified HTTP header compatibility with 304 responses
  • Shortlink HTTP header preservation
  • Pingback HTTP header preservation
  • Fallback to no caching if any error or problem occurs
  • WordPress Network compatible
  • nginx compatible
  • (optional) syslog messages of sets-gets-flushes

You can download WP-FFPC cache here:

This entry was posted in Benchmark, Tutorials. Bookmark the permalink.

3 Responses to Testing WordPress: the importance of PHP opcode cache

  1. This is really good reading, thanks.

    Another way to increase the capacity of your site is to also use a CDN. When we were doing similar tests a couple of years ago we managed to push to 1000 concurrent clients on a similar VPS to the one you guys are using and we had more problems with hitting the capacity of the loadtesting service and datacentre blocking by Amazon CloudFront than we did with the server itself, which sat there quietly chugging along.

    We’ll take a look at your plugin when we’re next looking into caching and performance solutions for WP.

  2. Peter Molnar says:

    Hi David,

    CDN is good, but most of the providers are located in the US, they are pretty rare in Europe.
    But that’s true, a CDN can make significant difference as well.

  3. I think pretty much every performance related post on the web includes the use of APC and its opcode cache and rightly so since it’s pretty much a no brainer.

    This blog post doesn’t mention the APC configuration. I just want to point out that for a WordPress website the default 32MB shared memory that is assigned might not be enough in all cases. Especially if you run multiple sites on your VPS which I’m sure a great deal of people do. If there isn’t enough memory to cache all PHP files that your web server will execute then you’re going to lose some of that performance gain.

    I’ve done a post about it over on the scaling WordPress blog:

    Nice work on the WP-FFPC plugin by the way. I haven’t tried it yet but I will do. I’m on the lookout for a page cache that can be accessed directly from Nginx to save on unnecessary PHP requests.

    I thought I might have been able to access the cached pages stored in Memcached by the batcache plugin but the hash looks a little more complex to work out on the Nginx side.

    Any plan to make WP-FFPC work like batcache and only cache under high load?

    Any plan to include a “$unique” array like batcache for storing separate cache files for mobile etc?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>