Subscribe to blog updates via email »
WordPress Optimization: How I Reduced Page Load Time by 75%
Note [February 11, 2013]: Since writing this article, I found administering my own server to be a bit over my head. I got sick of getting hacked, update WordPress, and trying to manage my own CDN. So, I’ve been experimenting with various hosted WordPress solutions. These are like hosting companies, but they keep your WordPress installation up-to-date, fast, and secure, for a slightly higher rate than working with your own server.
I have hosted various sites on three different WordPress hosts over the past couple of years, and have finally settled on WP Engine. They are reliable, have great support, and serve things up fast. I’ve lined up a special WP Engine coupon with them that will save you some money.
I’ve also written a WP Engine Review, and you can use their speed test to see how your site performs. I’m a member of the WP Engine affiliate program, so if you sign up with them, I will get a commission.
WANT TO WRITE A BOOK?
Download your FREE copy of How to Write a Book »
(for a limited time)
WP Engine does cost a bit more, so if you’d prefer something cheaper (though not as fast), I’ve written a tutorial on the Design for Hackers blog on how to create a WordPress blog on a Hostgator free trial.
—–
I heard rumblings last year that Google would start altering their rankings based upon speed of page loads. This was confirmed a couple of weeks ago on the Google Webmaster’s blog, and – while they say that their new speed standards will only affect 1% of searches – you can bet that portion will rise in the future.
A few weeks before Google’s announcement, I decided it was time to start looking at site performance. I moved a couple of my sites, including this one, from my Dreamhost Shared server, to a Virtual Private Server (VPS) on The Rackspace Cloud. Additionally, I implemented a few other performance enhancements that I’ll cover below. From all of these changes, I cut load time of pages on kadavy.net by 75%, and my Webmaster Tools performance graph now looks like this.
Also, Googlebot now crawls my site 90% faster. A summary of what’s to follow:
- I reduced average page-load time from 12 seconds to 3 seconds, saving my visitors almost one week of time per month.
- I did this by first switching from a Dreamhost Shared server to The Rackspace Cloud.
- I then used the W3 Total Cache WordPress Plugin, and served my media files from Amazon’s Cloudfront CDN, from multiple subdomains.
Great web publishing platforms like WordPress have made it easy for just about anyone to publish information and have it seen by the world, but as Google starts favoring sites that have the resources and knowledge to optimize page load time, some publishers’ messages may not have the reach they once did. Exacerbating this problem is that information on website optimization is somewhat complicated and assumes a considerable amount of technical knowledge. I hope to share my experience with improving the page load time of my WordPress site in as plain of language as possible. I’m a designer by training, and get by how I can as a developer. So, maybe some folks out there who know more than I do about this stuff will have some knowledge to offer. Maybe I did something completely wrong, in which case, let me know in the comments!
Servers: What’s the difference between Shared and VPS?
With shared hosting – such as Dreamhost‘s ($50 off with the promo code KADAVY) – your sites are all on one machine with a whole bunch of other sites, sharing all of the resources (CPU usage and RAM usage). You also don’t have much control over the configuration of your server, such as what PHP modules are activated (of which, there are probably way too many), and the configuration of your PHP.ini file.
With a VPS – The Rackspace Cloud, specifically – your “server” is a piece of a machine, with CPU and memory resources dedicated just for your piece of it. You can choose what flavor of Linux you have installed, how your Apache server is configured (if you want to run Apache at all), how your PHP is configured – you can control pretty much everything. The drawback is that you have to administer it all yourself. This was challenging for me to figure out, but as you can see the speed payoff is pretty amazing.
Why not use Dreamhost’s PS?
As I evaluated my options, I considered simply upgrading to Dreamhost PS. All I would have had to do was press a button to do this, but I had heard not-so-good-things about Dreamhost PS – and most importantly, my MySQL database would have still been on a shared server. I would have to pay extra if I wanted my database on a nicer server. This seemed pointless to me, and didn’t sound like a VPS at all. I wasn’t keen on administering my own server, but after help from some nice people at Jelly (especially Chris Chandler from Flatterline) things are going okay so far.
How much does the Rackspace Cloud cost?
I’m not really sure yet, because I haven’t gotten a bill, but it looks like you can get started for around $12 a month, with a server with 256MB of memory. There are bandwidth and storage fees on top of this, but they seem pretty low. The coolest thing about The Rackspace Cloud so far is that you can scale your server up and down in a matter of minutes, and only pay by the hour, based upon the size of the server. My two WordPress sites, totaling about 60k pageviews a month, are currently on a 1024MB server, which I hope will cost me less than $50 a month, but I’m starting to make money on my properties, so the expense is worth it for me. If you don’t have much revenue, it may not be worth it for you – or you could increase your revenue: something I hope to write more about in the future.
Using the Rackspace Cloud
Once I signed up for Rackspace (they called me within 15 minutes of signing up, to confirm, before I could start using it), I signed in and created a server. When doing this, you can pick the flavor of Linux that you want to use. I didn’t really know what this meant, but I was advised by a friend to choose the latest version of Ubuntu they had. So I chose 9.10 (Karmic Koala). I also could have chosen one of various Windows servers. After selecting the Linux flavor, I was able to name my server, and select the size of server that I wished to use. I started off with 256MB, but I very easily scaled up later on. After a few minutes, the server was all set up, and I got a confirmation e-mail, with my dedicated IP address, and login and password.
Setting up the rest of the LAMP stack
Now that my Linux was set up, it was time to install Apache, MySQL, and PHP. I SSHed into the server using Terminal on the Mac. That command looks like this (but I used my actual IP address):
ssh root@111.111.11.111
Setting up Apache, MySQL, and PHP – and phpmyadmin – was super easy thanks to this great article in the Ubuntu Documentation.
Transferring the Data
Now I was ready to get the data over to my new server. I SSHed into my Dreamhost server (you may have to contact support to get this enabled), and created an archive of kadavy.net:
tar -cvf kadavy.tar kadavy.net
I then transferred that archive over to my Rackspace Cloud server using Secure Copy:
scp kadavy.tar root@111.111.11.111:/home
Then I decompressed the file on my Rackspace Cloud:
cd /home
tar -xvf kadavy.tar
Setting it up
I then used PHPMyAdmin to export my database from Dreamhost, and import it onto my Rackspace Cloud instance. I had to change a few settings in the options table of my database to match the IP address of my server, rather than my domain, so that it would run properly before setting up my DNS. I also made a few changes to my wp-settings.php so the installation was pointed at the right database.
Using the easy instructions from the Ubuntu documentation, I set up the virtual host on Apache, and started up the server.
After I felt everything was right – and after messing around with optimization tricks below – I pointed the DNS to this new server. Rackspace has a DNS management tool, but I found that GoDaddy (my registrar) had more user-friendly DNS management.
Optimizing WordPress / The Front-End
Now that I was on a much faster server, there were a few other things I learned that made my pages load even faster. After learning these tricks, I found that there was one WordPress plugin that used many of these tricks. I used the YSlow Firefox plugin to benchmark the speed of page loads, and also to get tips on ways I could optimize my pages. Here’s some of the more important tactics I learned.
Page Caching
The most popular WordPress optimization advice I found was to cache the pages. Instead of having to hit the database every time a page is called, caching allows your server to serve up static HTML. The server doesn’t have to process all of that PHP and build the pages from the database. There are several plugins for WordPress which automate this, one of them being W3 Total Cache, which I’ll talk about more in a minute.
Using a CDN (Amazon Cloudfront)
This was the most intimidating sounding advice I received, but it turned out to be pretty simple. A Content Delivery Network is basically a bunch of servers around the world through which you serve your larger files, such as images, CSS, and Javascript. When someone visits your site, the assets are served from the closest server to them, thus speeding up load time. I had heard of Amazon Web Services many times before, not really understanding what it was, but their Cloudfront service is a very cheap CDN (looks like it will cost me less than $1 a month). You can sign up for it at aws.amazon.com, and can freely upload assets using S3 Browser, amongst other applications.
Once you’ve signed up for Amazon, you can create a “bucket” on Cloudfront by clicking on the Cloudfront tab, then Create Distribution. Name your bucket, and you can set up CNAMEs (media1.mydomain.com, media2.mydomain.com). You’ll have to set these up in your DNS with your registrar as well. I’ll get to why you would even want to do this in a bit, but this gives you various subdomains you can use to access the same resources in your bucket. In addition to these subdomains, you’ll be able to access your resources at locations indicated under “Domain Name” and “Origin Bucket.”
You can get the Access Key ID and Secret Access Key required to upload resources via S3 Browser by creating an Access Key under Account > Security Credentials.
The most daunting thought about using Cloudfront was uploading all of my resources, and pointing my code to them, but there are a number of WordPress plugins that automate parts this process, including W3 Total Cache, which I’ll cover in a bit.
Using Multiple Domain Names
Why did I set up multiple subdomains on my Cloudfront media bucket? It turns out, the HTTP spec states that “A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy,” and, even though this spec was written in 1999, many browsers still adhere to this specification. So, if you are accessing more than two assets from one domain – be they images, CSS files, or Javascript files – many users’ browsers will only download them two at a time.
The workaround for this is to set up multiple subdomains that all point to your Cloudfront bucket (media1.mydomain.com, media2.mydomain.com, media3.mydomain.com, media4.mydomain.com), and rotate through them as you code URLs to various media assets. I’ve been advised that 4 subdomains is plenty, as this will allow any browser to download as many as 8 files at once.
Doing it all (almost) with W3 Total Cache
The caching component of the advice I found has been around long enough that not only is there a WordPress Plugin called WP-Cache, there is also another plugin called WP-Super Cache. Now, there is the amazing W3 Total Cache, which not only caches your pages, it also minifies (removes line breaks to save space), and uploads files in your media library to a CDN, such as Amazon Cloudfront.
While W3 Total Cache does upload to a CDN your wp-includes, theme files, CSS, Javascript files, and any other files you specify, it does not soon will change the paths to any images within your CSS files , and in your theme files, so you have to do this manually. But, since W3 Total Cache doesn’t soon will support the multiple subdomains I was talking about, this is probably for the best. I manually inserted different subdomains into my CSS and theme files.
Be careful with minifying your Javascript files, as I found that doing so broke Google Website Optimizer tracking code.
Other Optimization Tricks
- CSS Sprites: This is the technique of putting all of your design graphics in one giant file, and selectively displaying parts of it through CSS. This reduces the number of HTTP requests, and the total size of graphics to be downloaded, this reducing load time by quite a bit. It’s also a bit of a pain in the ass, so I’m saving it for a future redesign.
- Putting CSS and Javascript inline instead of in separate files (for pages that are usually the only one visited): Since I have a couple of pages that visitors hit from a search engine, and then tend to leave, I did this on a dedicated template for a few posts. This really only helps if the page in question is the only page a user is likely to visit on your site. This is not a good technique for visitors that visit multiple pages, as they will have to re-download all of your styles.
- Gzip files: but Amazon Cloudfront does this automatically.
- Yahoo outlines some other best practices you may want to try, depending on how much effort you’d like to put in.
It still remains to be seen whether this performance enhancement will improve my Google rankings, but I hope this document helps some less technical publishers understand just how much impact they can expect from the choices they make in hosting platform and front-end development.
P.S. If you do decide to use The Rackspace Cloud, I sure would appreciate it if you signed up through this link. Clearly they’ve worked well for me, but I wouldn’t mind the referral bonus.
Elsewhere on the web: How to speed up your blog (the non technical guide)