Viewing cache View all News

WordPress Static Page Cache

WordPress is a dynamic application. When a page is requested, the application loads hundreds or thousands of files into memory, makes dozens or hundreds of database queries, and eventually, crafts a static HTML document, which the visitor’s web browser can then render as a web page.

All of this happens every time someone pulls up a web page.

As you might imagine, the complexity of such operations can put quite a strain on humble web servers. As traffic levels increase, the struggle to meet the demands can result in WordPress sites slowing to a crawl or worse, crashing.

Investments in better hardware will postpone the inevitable, but to really address the problem head on, one must eliminate the dynamic nature of WordPress.

By saving a static copy of the page being generated to the server, the chain of events must only occur once; after that, the server need only hand over the ready-made page when visitors request it.

This is the perfect solution for content-driven web sites like blogs and portfolios. When changes are made to the database (e.g. a new post is published, or an old one is edited), the author can simply clear the cache and the site is good as new!

This solution is not so good for interactive user sites like stores and forums, where access to realtime data or personalized templates are required. At the end of this article, we’ll examine some tricks that might still offer assistance for these types of sites.

W3 Total Cache

There are a lot of caching plugins available to WordPress, but none are as comprehensive as W3TC. It is available in both free and premium versions, however for users looking at just the static page caching functionality, the free version will suffice.

First things first, install it.

Once activated, you’ll find a “Performance” tab in the admin menu. Go to “Performance” > “General Settings” to enable page cache (to disk). Now go to “Performance” > “Page Cache” to configure settings specific to page caching. For most sites, the default settings will suffice. If you have any pages that need to be served dynamically, such as a contact form or a page displaying randomized content, you can add it to the list of “Never cache the following pages”.

That’s it!

You can verify page cache is working by looking at the source code of a page on your site. You should see something like the following at the end:

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/
Page Caching using disk: enhanced
Served from: brightbrightgreat.com @ 2015-07-11 10:17:07 by W3 Total Cache -->

If page cache is disabled for logged in users, you might instead see:


<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/
Page Caching using disk: enhanced (User is logged in)
Served from: brightbrightgreat.com @ 2015-07-11 11:14:21 by W3 Total Cache -->

The (User is logged in) lets you know that page cache would be used, were it not for the fact that logged in users are specifically excluded from it.

W3TC has a lot of features beyond page cache that are worth checking out. “Minify” will attempt to compress static documents before saving them to disk, which can result in faster load times for users.

Minification can break things in unexpected ways, so if you enable it, carefully double-check that your site is still working as expected (you can use an Incognito/Private session to view the site as a regular visitor would see it without having to log out of your account). If your server is already gzipping requests, you probably won’t see substantial performance gains from Minify.

To completely clear your static page cache, click “Performance” > “Empty All Caches” in the admin toolbar. If you forget to do this, the cache will empty itself automatically eventually.

Advanced

The biggest disadvantage to using static page cache is that pages are, well, cached. If a web site allows users to log in and then shows them personalized content (e.g. “Welcome back, Jane!”), static page cache won’t work correctly; all visitors will receive the same static page. Either Jane won’t see her message, or everyone will see Jane’s message.

One possible workaround is to disable cache for logged in users, but allow it for everyone else. If your site users are simply low-privilege WordPress users (e.g. subscribers), this is the default behavior anyway. But cache can also be disabled by the presence of a cookie; if user sessions are controlled through custom code, set a cookie at login (and remove it at logout), and add the cookie name to “Rejected cookies” list.

For sites where the session-specific variation is minimal, it might be preferable to maintain static page cache for all users, and let Javascript make any necessary adjustments at runtime.

A good example of this would be a storefront that displays the current cart count in the toolbar. As items are added to the cart, the count could be written to a cookie, which Javascript could then read and plop into place. Highly specific pages like the shopping cart could be individually excluded from cache, ensuring they are always up-to-date.

Lastly, it might be necessary for sites to clear the page cache programmatically. For example, if a product page lists its availability, that figure should be adjusted when a new order is placed.

To do this, make a wrapper function like the following (add/remove caches as necessary), and include calls to it where needed:

function my_cache_clear(){
	//clear W3TC page cache
	if(function_exists('w3tc_pgcache_flush'))
		w3tc_pgcache_flush();

	//clear W3TC database cache (comment out if not using)
	if(function_exists('w3tc_dbcache_flush'))
		w3tc_dbcache_flush();

	//clear W3TC object cache
	if(function_exists('w3tc_objectcache_flush'))
		w3tc_objectcache_flush();

	//clear W3TC minify cache
	if(function_exists('w3tc_minify_flush'))
		w3tc_minify_flush();
}

These techniques are no substitute for good coding and asset optimization, but they can give your site a boost and help make sure pages load quickly and efficiently.

Posted By
Josh Stoik

WordPress Object Cache

It is not unusual for WordPress to run dozens or even hundreds (yikes!) of database queries when putting together a page. What’s worse, these queries aren’t the sort from children’s bedtime stories. They’re the dirty ones, full of temporary tables, JOINs on JOINs on JOINs, generic data types, and insufficient indexing. They’re the MySQL equivalent of The Wire.

As traffic loads increase, these computationally-heavy operations can quickly lead to a bottleneck, making your site sluggish or bringing it offline altogether.

To get a better idea of your own database use (or abuse), install a plugin like Query Monitor, which puts detailed query stats in the admin toolbar.

If you’re nearing the limit of what MySQL can handle, there are a few basic things you should consider doing:

  1. Go through your plugins and deactivate and delete anything that isn’t being used.
  2. Set reasonable post limits (10 or fewer) for archive pages.
  3. If you have a custom theme, try to minimize the number of secondary queries being run inside The Loop.

Beyond that, well, that’s the purpose of this article: Object Caching!

WordPress has the ability to cache query results (and other key/value data) in memory for later retrieval so it doesn’t have to pester MySQL on repeat requests.

This can dramatically reduce the load on MySQL, while maintaining comparable speed.

The main disadvantage of Object Cache is that objects are, well, cached. This means that changes made in the backend might not be immediately reflected on the front end.

This can be a deal breaker for applications with transactional data like e-commerce sites, unless the code contains strategic calls to wp_cache_flush(). But for content-driven sites like blogs and portfolios, it can be the perfect solution.

Object Cache also takes over handling of “transient” data, which otherwise get stored in the wp_options table. This will both speed up plugins and themes that rely on the transient API, and also reduce bloat in the database (there is no automatic garbage collection process run against wp_options, so data remains forever, and ever, and ever… (unless the same cache key is requested again)).

WordPress Object Caching is designed with extensibility in mind. All it needs is an API for key/value storage and retrieval.

There are innumerable candidates for the job, so let’s just focus on some of the most common:

XCache

XCache is my favorite PHP opcode cacher (opcode cache, incidentally, will also speed up the execution of your PHP scripts in general).

It is lightweight, scalable, and supports the latest versions of PHP.

To get started, install the XCache PHP extension (available in most Linux repositories), tweak the INI settings* (variable cache is the relevant feature here), and restart PHP.

After that, you can then enable Object Caching in WordPress by installing XCache Object Cache Backend or a more comprehensive caching solution like W3 Total Cache.

If you have multiple sites running on the same server, you need to ensure you are running version 3.0.3 or later.

The XCache extension comes bundled with admin scripts you can copy to your web root to get an idea of how cache is being utilized. You should install this after it has been running for a while to see if the memory allocations need to be raised or lowered (just make sure you restrict access, and delete it when you’re done!). Remember, the memory settings are per-process, so don’t get carried away.

APC

APC is another PHP opcode cacher, but it is no longer actively developed.

Unless you are running an older version of PHP or your hosting environment comes bundled with it, XCache is a better option.

To get started, install the APC PHP extension, tweak the INI settings, and restart PHP. You can install a standalone plugin like APC Object Cache Backend or, again, go with something like W3TC.

There remains, however, one excellent use case for APC: Facebook’s HHVM engine supports it out of the box! If you have already replaced PHP with HHVM, just install the APC Object Cache Backend plugin and you’re good to go.

Redis

Redis is a powerful key/value caching solution with support for multiple servers.

For complex web applications consisting of multiple servers, it is an ideal solution as the cache can be shared across more than one machine.

For more simple setups, it is a bit much, and noticeably slower than XCache or APC.

To get started, install the Redis server and PHP extension (if you are running HHVM instead of PHP, the “extension” is built-in). Once you have that configured, you can install the Redis Object Cache plugin.

Posted By
Josh Stoik