A few months ago, stared noticing how consistently slow my blog was. More than 3 seconds per page load is just terrible. That’s slow enough that some people would think the site just isn’t working and would navigate elsewhere. Being an engineer, I decided to see what I could do to improve the load times without paying a ton for fancy hosting. This a list of things that I used to improve this blog’s performance.
Use tools to find bottlenecks
These tools were invaluable throughout the process. Very often I need to check something like the load times for a resource or make sure that the page was using the CDN correctly. The network graph also allows you to easily see the slow resources. For example, I was able to see exactly how much of the time was spent just my blog’s index.html file.
YSlow was quite helpful. It pointed me in the direction of many of the items on this list such as combining/minifying CSS and using gzip.
Caching blog plugins
I originally used WordPress for powering this blog. It’s just packed with features and quite easy to use, but it renders each page dynamically in PHP, which isn’t fast on low-cost hosting. When I first profiled the page, the majority of the page load time was spent waiting for WordPress to render pages, before it even started sending back any content.
I only found one caching plugin that worked well with my hosting provider since they impose limitations on PHP for security that break most caching plugins: Quick Cache. I found that it reduced the html index load time from about 3 seconds to 1.5 seconds (very rough numbers). I didn’t notice any downside and never had issues with cache invalidation. More aggressive caching plugins such as WP Super Cache will even generate static HTML which would probably speed it up even more.
Switch hosting provider
I switched from GoDaddy to NearlyFreeSpeech. Both are low-cost shared hosting providers. The switch seemed to help, but I forgot to benchmark before moving so I can’t really say how much.
- Truly horrible management interfaces
- Mediocre performance
- Acceptable prices at about $5/month
- Good management interfaces for advanced users ex: phpmyadmin for MySQL and SSH and SFTP access
- Mediocre performance
- Very low cost at about $0.04/day for a small site.
- PHP safe_mode is always on
- No mod_gzip in Apache
Switch blogging software
I switched from WordPress to MovableType. MovableType serves up static HTML pages that are only regenerated when publishing a new entry. The removes the overhead of loading PHP and executing a script and making database queries for every page request. This was probably the single most dramatic performance increase, but also the one the took the longest time, even with MovableType’s import feature.
Serve gzip compressed files.
Gzip is an easy way to reduce transfer size and therefor time. mod_gzip makes this brain-dead easy, but my hosting provider doesn’t support it. The solution I found is to manually run a script to compress every file from
file.ext.gz. Combine that with an Apache rewrite rule and you’ll automatically serve compressed files for browsers that support it. The annoying part is that I have to manually rerun the script after changing any file.
Use a content delivery network
I’ve always thought of this as an advanced technique only used for very popular websites, but then I found out that Amazon CloudFront is actually extremely inexpensive if you only need small amounts of traffic since Amazon only bills by usage. I’m using it for small static content such as images, CSS and JS so the overall size of the transfers is tiny. The speed up is tremendous— those files pretty much disappear from the load times graph. It’s definitely worth the pennies per day that it costs.
Setting up CloudFront was easier that I expected. Amazon gives you a randomized domain name that acts like a fast proxy for your real domain. The only thing you have to do is change the links in your HTML from
http://E123456.cloudfront.net/styles/style.css. Gzip compression is transparently passed-through. There are a couple of ways to do invalidation, but I’ve opted for the easiest— just change the URL when changing the content.