On wpPERFORM.com, we’ve included aggressive WordPress caching to optimize the performance of your WordPress powered site. Caching has a dramatic impact on the speed at which we serve up your site. It also has important ramifications for how you and your users interact with your site. For general background on caching in WordPress, check out the Codex article on optimization and caching.
Caching comes in many flavors that serve different purposes. We’re not going to cover generic types of caches, such as browser caches, here. Instead, our focus is on what’s specific to our setup. On wpPERFORM.com, we’ve implemented:
- multiple opcode caches
- page caching
For those interested in disabling page-caching on any wpPERFORM-hosted URL, just add a query string to the URL as shown in the example below.
We’ll describe each in more detail.
PHP version 5.5.0, the Zend Opcache extension is included by default since its development is now open-sourced in a GitHub repository.
PHP, the programming language for a large portion of the WordPress code, is an interpreted language. That means the programming instructions have to be compiled to a format understood by a server’s processors, or opcodes. Without an opcode cache, every execution of the same instructions requires them to be recompiled. To the extent that the same instructions are executed over and over, that’s an inefficient approach. With our Zend Opcache, the compiled opcodes are stored in fast memory, which eliminates the need to recompile them for each use. We size our opcode cache to provide for 100% cache hits with at least 30% of total cache remaining free.
We previously used Alternative PHP Cache, or APC, another opcode cache. Our internal tests as well as reports from Alessandro Tagliapietra and Ricard Clau show that Zend Opcache is faster than APC, and in many cases a lot faster. For example, Alessandro Tagliapietra’s tests show that Zend Opcache processes about 60% more requests per second than APC on Nginx with 50 users.
memcached to serve as an in memory key-value store. Without a memcached object cache, these key-values would not persist between page requests. Regenerating the key-values would trigger database requests that are otherwise saved by our memcached cache.
WordPress stores its data in a MySQL database. That includes post and page content, along with all settings, but doesn’t include uploaded files, such as media files. When a page is requested by a webserver, WordPress uses programming code, largely PHP, to retrieve data from the database and render the page. Without page caching, each request for the same page requires the same programming code to run to generate the page output every time. That’s an inefficient process. Fortunately, our page cache addresses it. Page caching is the single biggest optimization for a web server.
To simplify our discussion, let’s define a typical visitor as a user a user that isn’t logged in and hasn’t left a comment. On first visit from a typical visitor, we create a static HTML version of the page. In other words, we let the programming code render the page for the first typical visitor, and thereafter, for each typical visitor over the next 1 hour period, we serve the static HTML version of the page. That eliminates the need to regenerate pages for subsequent visitors. Static HTML pages are typically small in size and serving static content is one of the particular strengths of our webservers.
For all requests other than 301 redirects, we set a cache life of 1 hour to allow typical visitors to see reasonably fresh content but still serve most pages from a static page cache. For pages that are redirected with a 301 redirect, we set a cache life of 1 day based on our experience showing that these pages change less frequently.
If you or a visitor is logged in or has left a comment on your site, we don’t serve your page from our page cache. That allows logged in users to edit fresh content and commenters to stay abreast of the latest discussion. We determine your logged in or commenter status from a cookie, which is specific to a browser. Therefore, if you have multiple browsers open on your computer at the same time, it’s possible that you see a cached version of a page in one browser where you’re not logged in and a live version of the same page where you are logged in.
We also try to make our cache entries as specific as possible to make sure we’re serving a cached page to the same type of request. For example, we don’t serve the cached contents of a HEAD request to a visitor making a GET request for the same page.
You can disable our page cache on any URL hosted by wpPERFORM using a query string, as shown in the example below.
We’re not using a plugin such as W3 Total Cache or WP Super Cache to generate our page cache. Instead, we’re leveraging the built-in caching capabilities of Nginx and its
fastcgi_cache module to generate our cache and perform cache maintenance, such as periodically deleting old cache entries.
All page caches represent a compromise between producing the fastest performance and giving users access to the freshest content. If all users have access to the freshest content that’s stored on disk, there’s effectively no page cache. If all users are served cached content for maximum performance, routine site maintenance becomes a painful chore, and sites that depend on rapid fire comment flow turn quiet. We think the balance we’ve struck lets typical visitors – the bulk of your site traffic – enjoy the speed benefits of caching.
Because our cache management applies across our entire network, you can’t turn caching on or off for your individual site, and you don’t have to worry about managing your cache. For the overwhelming majority of sites, our approach to caching is a big benefit. On the other hand, for those sites that want finely-tuned control over their individual caches, our centralized approach might create some problems.
If you’re wondering about how our approach to WordPress caching will impact your site, just reach out to us.