Optimizing WordPress – Tips for Speed
WordPress is crap, but it is the best crap we can get. When your website, with WordPress sitting in the back, starts to pick up traffic, it will slow down and become unresponsive. Adding hardware will help, but correctly implemented load balancing and load distribution across more than one computer can be tricky and expensive. Trying to optimize WordPress and the web server itself usually gives better short-term results. In the long run even this won’t help and it will just postpone the inevitable, you will have to cluster in one way or another. I am not going to talk about clustering and load balancing today, I will focus on optimizing your WordPress. Newbie friendly, yet hardcore, meaning that I will provide explanation for all the complicated stuff.
What is slowing you down?
This is essential question with all optimizations. Figure out what is causing the slowdown! I have worked in IT for all my life and I was called to help with optimizations on all sorts of things. Let it be a local network or some internal database for a service provider, the procedure is always the same. Figuring out bottle necks and getting rid of them.
With WordPress, there is no big secret, PHP is slowing you down1. The first thing you can do, is to try to localize the bottleneck. It could be the new plug-in you just installed and it turned out that it does not scale as it should. Get rid of it or go around it. As with the most WordPress installations the slowdown will be more global. Everything will be slow, sluggish and unresponsive.
Optimize where it makes sense
Second thing that you need to be careful with. I had the pleasure of working with people who spend weeks on optimizing a function that was perhaps called once every few hours. Don’t go and optimize things that are accessed rarely, for example the ‘My Life Story’ page on your blog. No real need unless it is blocking the site and you are sure that it is the cause of your troubles.
WordPress plugins that will help you
Now, lets take a look at couple of WordPress plugins that will greatly improve responsiveness of your blog.
WP Super Cache – Properly configured Super Cache plugin is a must. Since we know that PHP is slowing us down we need to take it out of the equation. This plugin will generate static HTML files and with a little help of the web server it will serve those static files to non-logged in visitors if they didn’t post any comments on your site. This accounts for the majority of the traffic.
Getting rid of the dynamic stuff is probably the most important thing that you can do and it will also matter the most. PHP is eating a lot of your resources away and compared to this, serving static pages is easier than eating pancakes.
WP Minify – Scripts and style sheets can become quite large and you will probably end up with more than one of each. Minifiying them means erasing all the extra characters that are there for readability. Web browsers usually don’t need them.
Here is an example of ordinary CSS that comes with Sociable plugin and below it is the minified version:
div.sociable { margin: 16px 0; } span.sociable_tagline { position: relative; } span.sociable_tagline span { display: none; width: 14em; } span.sociable_tagline:hover span { position: absolute; display: block; top: -5em; background: #ffe; border: 1px solid #ccc; color: black; line-height: 1.25em; }
div.sociable{margin:16px 0;} span.sociable_tagline{position:relative;} span.sociable_tagline span{display:none;width:14em;} span.sociable_tagline:hover span{position:absolute;display:block;top:-5em;background:#ffe;border:1px solid #ccc;color:black;line-height:1.25em;}
It might not seem much, but CSS files and JavaScript files can grow pretty big. TWM website has CSS that is larger than 12kB, properly minimified is just a bit more than 9kB. Three kilobytes less for server to send and for the client to process.
WP Minify will, before the page is displayed, catch all the style sheet and java script files, glue them together, minifty them and then output them. The good part is that Minify plugin can work together with Super Cache plugin. Minified versions of your files are then cached and sent to the clients.
Make sure you run some tests before you start using it. Minify doesn’t work with slightly hacked Zemanta plugin2 and WP-Cumulus plugin3 for the pretty tag cloud. So make sure that it doesn’t make a mess with any of your Java Scripts files or it could in theory mess up your Style Sheets too.
Warning: If you are adding extra CSS or JS files in the configuration interface that need to be minified make sure that text area where you enter file names doesn’t end with an empty line. It will break the plugin.
So much for the WordPress
Not much more can be done in WordPress itself unless you are determined to hack into it. You could do that, but then you will have to do it each time you upgrade WordPress. And you will want to upgrade every now and then. Now, comes the hard part, optimizing general page performance. We did great with minifying everything and serving it as static content and this will matter the most on the server side.
The question now is where else can we gain some speed? Where are we losing precious CPU cycles and sometimes even more precious bandwidth? Maybe if we try to minimize number of requests to the web server itself?
Optimize your theme
Get rid of all the theme images if you can. That means, not getting rid of them entirely, but put them in a single static bitmap and then use it as CSS sprite. This will greatly reduce the number of requests on your web server. The whole procedure is too long to describe here, but Google will return plenty hits on CSS sprites. The theme you see here had more than twenty images and we were able to merge all of them in to a sprite. Now CSS is taking care of displaying the correct part of the image. Client has to make only one single request to download the bitmap. In our case the bitmap was also smaller than all of the images together. Win – Win!
Keep your redirects at minimum
Redirects are a convenient way to point the client in a different direction. If you change the permalink of a blog post, WordPress remembers that. Them it performs a 301 redirect to the new address if someone tries to access the old one. 301 is an HTTP response code that is followed by a new URL and tells the client to go look to the new address for content. It is also called a ‘search engine friendly’ redirect. This is because search engines will most of the time remember that the location was moved permanently and they will use the new address.
Because of this, each redirected page will generate two hits on your web server. Avoid redirects and use them only when necessary.
Use trailing slashes
Make sure that you are using trailing slashes. When you are referencing something on your blog, a category for example, the URL should have a trailing slash. If it is lacking one Apache web server will automatically create a 301 redirect and add a trailing slash. And we learned above that redirects are not good, especially not the ones that are really unnecessary.
Right:
http://www.twm-kd.com/category/computers/software/
Wrong:
http://www.twm-kd.com/category/computers/software
Enable compression
Compressing plain text content can reduce payload up to 70% or even more and this saves precious bandwidth. Keep in mind that compressing small files, smaller than couple hundred bytes, can actually make them larger! Also if you are having CPU problems and your CPU can’t cope with the load, then you need to turn off the compression, but you will need to test this.
There is an option for this in WP Super Cache plugin. If you are not using Super Cache you will have to enable compression manually. To enable this across the site add the following line to your apache configuration:
SetOutputFilter DEFLATE
BrowserMatch ^Mozilla/4\.0[678] no-gzip\
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
# Don't compress images
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|swf)$ no-gzip dont-varyIf you are using Ubuntu Server or Debian GNU/Linux distribution then you will have to enable mod_deflate:
$ sudo a2enmod deflateThis will enable module deflate. Make sure that there are two symlinks in /etc/apache2/mod-enabled, deflate.conf and deflate.load. Then you will have to restart the web server.
Optimize your database
MySQL database can scale pretty well, but it has few problems here and there. One of them is not storing the data as efficiently as possible (for reading) and tables can get dirty. You will need to optimize them. If you are using phpMyAdmin for administration then you can do if from the main database view by checking the tables you want to optimize and then selecting optimize below in the operations. We here at TWM prefer the command line:
$ mysql -u USER -p wordpress mysql> OPTIMIZE TABLE wp_options; +-----------------------+----------+----------+----------+ | TABLE | Op | Msg_type | Msg_text | +-----------------------+----------+----------+----------+ | wordpress.wp_options | OPTIMIZE | STATUS | OK | +-----------------------+----------+----------+----------+ 1 ROW IN SET (0.02 sec) mysql> OPTIMIZE TABLE wp_posts; mysql> OPTIMIZE TABLE wp_comments;
Which tables to optimize? You can check this with SHOW TABLE STATUS; the data_free column will tell you how much space is allocated and not used by the table. With a lot of inserts, updates and deletes these numbers can grow and you want to avoid that. Depending on the traffic you will need to run optimize once a week or once a month.
Take care of proper caching of your static files
Your blog is more or less dynamic, but there are certain parts of your blog that are static and browsers can cache them. Images and theme files are two things that you can cache properly, even WordPress itself could be cached, but we mostly took care about them with Super Cache. Once I write a blog post, add images to it and publish it, I rarely change images that were attached to the post. That is why we can safely say that all the uploaded images can be cached for at least a year. Add the following lines to the .htaccess file in /wp-content/uploads directory:
ExpiresActive On ExpiresDefault "access plus 1 minutes" ExpiresByType image/gif "access plus 1 years" ExpiresByType image/png "access plus 1 yearss" ExpiresByType image/jpeg "access plus 1 years" ExpiresByType image/jpg "access plus 1 years"
Now you set the expiration date to one year in the future for all the images. If you decide to change an image inside the post just keep in mind that you will have to rename it, otherwise clients will not show the new image, but the old one that they still have it in the cache. Unless the client is specifically told to reload the page. For Firefox this is performed by holding shift key while clicking on the reload button.
Using lightweight web servers
You could use lighttpd and php fast cgi binary to render WordPress, this is an alternative solution but it needs more detailed description. Lighttpd is a replacement for Apache 2 web server. It is small and fast, but it lacks support for certain fetaures. WordPress can run with lighttpd, but you will need to deal with different URL rewriting rules that need to be fixed for SEO friendly permalinks and for Super Cache to work. This can be done, but it will be the subject of another post.
Client side optimization
We pretty much dealt with the server side and not much more can be done there. We can still do some optimization for the clients. Web page rendering is a process that is quite complex and web page developers can (and should) help clients with rendering. A very good tool for benchmarking load time and render time of your web page is Firebug add-on for Firefox. Combine it with Google’s Page Speed add-on and you have everything you need to help you with optimizations.
Optimize your images
Try to avoid HTML or CSS resizing of images. Bigger images will need more time to download and then browser will have to resize them. Much easier is to resize them first with some resizing and optimizing tool. You will also get better results and better quality.
Avoid third-party service providers
WordPress can be extended by a number of plugins, add-ons, themes and various other hacks. The problem with third-party service providers is that their services usually come with some cost. Clients will have to contact their servers and download their content which might not be as optimized as your web site is. This also means that the clients will have to perform at least one extra DNS lookup which takes some time and will need more requests to fetch all the content.
No complicated CSS
CSS rules are very inefficient sometimes so try to avoid too much nesting and don’t use eval in CSS. Avoid things like this:
Wrong:
#mylist ul li ul li { font-style: bold; }
Right:
.inner-list { font-style: bold; } .outer-list { font-style: normal; }
Use class selectors, they will make CSS a little bit longer, but client will render it much faster. If you minify it, the difference will be just a few bytes. Unfortunately you are limited with WordPress here. Writing efficient CSS for auto generated sidebar widgets is a pain since HTML returned by WordPress isn’t something they should be proud of. However, it is somewhat manageable.
Also make sure that you don’t have any leftover CSS rules in your file and you are not using it. Note that Page Speed will tell you that you have a lot of unused CSS, but keep in mind that not all of the CSS is used on the first page or on the other pages in your blog. Splitting this code in separate files is an idea that we didn’t try yet.
Speed, this is what you need
Load time for an average blog, with a decent internet connection4, should not be much more than a second or two. When there is no other traffic on the site. This should be a general guideline. When you start picking up traffic your server should be able to scale and if you are lucky enough the first bottleneck will be your network and that is good enough to shift the blame to your ISP, right? ;)
Next stage would be offloading static content to a third-party provider or a different server that you have dedicated for serving static content. Replacing Apache2 with lighttpd web server could also be a next step then in the end we will have to separate web server and database server. We will describe all this in one of the future posts here.


Hi,
some suggestions: I would also install phpMyAdmin (for manipulating MySQL databases and viewing usage statistics) and MySQLTuner for optimization suggestions. If you have lots of plug-ins installed, showing queries which are not using indexes allows you to identify and set missing indexes.
Another performance boost is gained by installing APC for PHP. It stores compiled PHP scripts into memory. Look at the statistics through apc.php and set apc.num_files_hint and apc.shm_size so that “Cache full count” will always be 0.
Hello, thanks for this post. I’m not a big fan of wordpress (seeing it’s code), but I liked the part about nested CSS, I didn’t knew that it takes down that much performance.
I’ve also used MONYog MySQL Monitor to optimize my database. I would also suggest to enable “log slow queries” and “log queries that do not use indexes” in mysql config… and properly rewrite SQLs that WordPress passes, if it’s possible for the user of it (or a plugin developer).
[...] Optimizing WordPress – Tips for Speed | Three Wise Men – Handy. Tags: wordpress web [...]