A word of warning: I haven’t implemented hardly any of the tips I’m about to share on this site. So don’t hate, participate. This blog is just for fun and I have no incentive to spend hours making it faster. MooreAndGiles.com is a good example of a site where I have implemented many of these techniques.
Today, Media Temple tweeted about an article on optimizing WordPress. While it makes some good points, I feel like there were some omissions that are worthy of sharing. So, that’s what I intend to do.
A word about caching.
No article on optimizing WordPress is worth anything if it neglects to mention the world of caching plugins. Such plugins are relied upon by millions and are a great way to achieve large performance increases in just a few steps. In fact, I have used such plugins to fix constant crashing on high traffic websites. The two I am most familiar with are WP Super Cache and W3 Total Cache.
While these have their place, there are a couple of reasons I tend to avoid them: mainly they can break things, and they try to do everything.
Now, I’m sure I just offended a few people. You can certainly work around the occasional (and often minor breaks). And more features isn’t always bad.
My hangup is that when they do break things, it is often difficult to troubleshoot because of the sheer volume of moving parts. There are so many nuances to the settings and it can be extremely difficult to find the right balance simply because it can be impossible to understand everything the plugin is trying to do on your behalf.
There are also many plugins that simply do not work with caching plugins. So some don’t even have a choice.
The goal here is to provide a list of things that nearly everyone should consider. These approaches are specific enough to be understood and minimalist enough to implement on a site that’s already established.
So, open your site in your favorite browser and start going through these files one by one. I found it helpful to use the YSlow add-on for Firebug in Firefox for this. Once you do a scan, you can view the components in a list and sort by size. This can give you a great way to prioritize what scripts you are going to tackle first.
If you are loading a script in header.php that is only used on one page, consider moving that include to a page template or wrap it in a conditional:
It is much faster for PHP to selectively unregister a script in functions.php than for your browser to download and process it.
You should notice immediate, tangible improvement as you work down the list.
Combine and minify
Now, I know what some of you are thinking “But you can do this with caching plugins!” Which is true. But, as we’ve already mentioned we’re trying to take a minimalistic approach.
Enter WP Minify.
WP-Minify has the magic ability to do all of this on the fly. Install. Activate. Done. It even minifies your HTML output.
If you have a problem with a script (as I did), the easiest thing to do is just add it to the list of exclusions. This allows you to reap 90% of the benefits while not changing your whole site to fit an optimization technique.
It also does some other little things for you like setting far future expiration dates and enabling gzip. (More on that later)
Alternative PHP Cache
This next tip only applies if you have a dedicated (virtual or physical) server with root access. PHP, while having many awesome qualities, is not known for being the fastest language in the world. This is mainly because it compiles and recompiles each script every time it is requested. Large operations like Facebook get around this by converting their PHP to C before publishing, but that isn’t a very practical solution for most people.
The most reliable way to improve PHP’s processing time is to use an opcode optimizer. This allows PHP to cache the compiled version of a page and rerun it from RAM on subsequent requests. This is tons faster than pulling from disk and recompiling! While there are several options in this realm, I think Alternative PHP Cache is the best choice for two simple reasons: 1) It is made by the PHP guys 2) it’s going to be built into PHP 6
Those are pretty strong reasons to get on board in my book.
Installing APC is relatively easy depending on your server config. There are many guides, often specific to the hosting service so I recommend you do a quick search before you get started.
Tweaking the settings can have a learning curve. I recommend you accept the defaults and then tweak once you have a chance to watch how it performs. The basic concept is this: you have a certain amount of dedicated cache where pages are compiled and stored. If this cache fills up frequently, it forces APC to flush the cache. If this happens often, you get what’s called cache churn which can actually hinder performance. Your goal is to have a large enough cache with a good expiration interval that allows the cache to stay relatively full without actually running out of space.
The nice thing about APC is that just installing it gives you a performance boost. But, since this is about WordPress, I recommend you install APC Object Cache Backend. This allows WordPress’s built in caching engine to fully leverage APC’s features. Read the instructions carefully…this isn’t installed like a normal plugin. The file actually goes in wp-content/ directly. Weird, I know.
Optimize those images
In addition to the above, images are often the slowest component of a page. Make sure you use JPEGs wherever appropriate and stick with PNGs only where lossless is absolutely necessary or where transparency is desired.
For JPEGs, pick a quality level that will satisfy your level of pixel OCD. The smaller the files, the faster they’ll load.
Once you’re done with that, you should use a tool that can losslessly optimize your images. I chose jpegoptim for this. Because I’m a nerd, I installed this on my server and setup a cron to run it against my images (of which I have many thousands on the install I’m referencing) weekly.
It’s easy to install and easy to run.
Just run this via SSH:
jpegoptim --strip-all /your/awesome/path/*
This will optimize each image, skipping any that will result in a larger size or no change.
(A word of caution, I found that this altered the permissions of my images…so double check the permissions after you’re done.)
In total, I was able to cut down my images sizes 10% with no loss of quality. That’s pretty cool.
Expiration and Gzip
Similarly, mod_deflate for Apache can gzip plain text files for faster delivery. The small cost of server overhead is well worth the advantages of smaller downloads. Processing time is cheaper than bandwidth (at least in this case).
To set this up, I suggest you look at this guide.
Beyond this, there are many other things you can do, but I’ve tried to cover only the things I think go most unnoticed and apply to nearly every install. I highly recommend you use the aforementioned YSlow plugin and Google’s Page Speed feature (available in Chrome and Firefox) for more performance tips. (And many of these were inspired by such tools).
In addition to what I’ve recommended, there are literally hundreds (if not thousands) of techniques out there:
- You can enable a conservative caching plugin like Hypercache (which hopefully plays nicely with the above plugins).
- You can optimize your MySQL tables (to reclaim free space).
- You can limit how many revisions WordPress keeps for each post by modifying wp-config.php.
- You can offload commenting to services like Disqus.
- You can change your scripts to run asynchronously.
- Etc. Ad infinitum.
As you can see, it would be fairly easy to waste* a lot of time here. (I once saw this called the “Holy Grail of micro-performance optimizations”) But, that being said, it’s worth diving into these things at least once. Your users will like it. Google’s page ranking will like it. And you’ll like it. You may even be amazed by the results. (I know I was!)
*If you see anyone telling you to get rid of references to get_bloginfo() in your templates in favor of hardcoded paths, tell ‘em to take a hike. That’s a truly pointless change and you won’t see any real performance gains…WordPress is smart enough to handle that stuff inexpensively.