How I sped up my Thica.net

Thumbnail credit: Amnemona

If you didn’t notice, I have another site called Thica.net - Vietnam poetry network, a WordPress (what else) powered blog dedicated to poems in Vietnamese. The site is receiving about 60K of views per month, which is 12x to that of the moment when it was started back on March 2008, and I’m rather happy about it.

About one month ago, Thica.net started to become very slow and tent to produce strange problems. More than often it threw 503 Internal Server Error just when I attempt to add a new post, or 404 Page Not Found for a page that I knew it was there, such as admin panel, plugin section etc. After some deep look inside, I decided that my site was too bloated and then it was time to optimize things to start it up. To admit, the result is nowhere near perfection, but it satisfies my need. So I think I’ll share with you here.

1. Eliminate unused plugins

Plugins
Original image by smackfu

Being a developer, I’m a big fan of plugins and addons. My Firefox has about 30 addons, ranging from Adblock Plus to UltraSurf (I’m living in a communist country FYI) and YSlow. Similarly, Thica.net had like 50 plugins, active and inactive alike. So you know, plugins power up WordPress in many ways, but on the downside slow it down because of all the added functions, hooks, data and so on. Some plugins are even terribly written (like one random post plugin which gets ALL posts from the database and uses PHP loop to get 5 random posts - WTH) and may cause serious problems: slowness, security holes, or even crashes your site.

So I dedicated my time filtering the plugins - which were really needed, which may be replaced by hacks and/or other inexpensive methods, which may be replaced with another plugin not as bloated, and which were totally useless. For instance, Askimet, Ozh’ Admin Drop Down Menu, Google XML Sitemaps, and Login LockDown were definitely kept. I’m now using my own functions to get the random and most read posts, searching for a SEO plugin in place of All In One SEO Pack as for some reasons Platinum SEO Pack didn’t fit my needs, and have trashed away tens of unused plugins. By “trashing away”, I mean deleting from the hard drive, as inactive plugins still waste WP resource - it still has to look them up and check for their status anyway.

2. Use a total cache solution

Database
Original image by adesigna

To a busy application - web or non-web alike, caching is vital. For as far as I know WordPress is not as bloated as other CMS (Joomla, Drupal, Magento to name a few), but its performance has rooms to be improved. I had been using WP SuperCache for quite a while and the performance was good enough, until the problems occurred and I realized that it had some extra features that I didn’t need at all. Then I sought out for some alternatives, like W3 Total Cache, Crazy Cache etc. HyperCache is where I stopped at - just a matter of personal opinion, and I’m happy with it so far.

But HyperCache alone was not enough in my case. Don’t you know that for a complete page to be served, WordPress has to make like a bunch of continuous calls to the database? My Thica.net for instance, makes an average of 50 MySQL queries for the home page and 80 to 90 queries for each single page. That’s rather expensive isn’t it?

Lucky me, there’s another kind of caching solution called database caching. As most of the query results don’t change from time to time - the post content, the categories, the tags… often remain the same - they can be cached for later use. For this purpose I installed DB Cache Reloaded and - just like magic - almost all of the queries (85 over 90 for example) are now served from the cache. You must admit, that’s a huge improvement. My host should thank me for not bombing their server!

3. Staticalize WordPress variables

Plugins

WordPress is so flexible - almost anything can be customized. That’s definitely great. But sometimes the greatness comes a bit too far from necessity. If you open a normal header.php file from a normal theme, 99% chance is you’ll see these lines:

<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
<title><?php wp_title('«', true, 'right'); ?> <?php bloginfo('name'); ?></title>
<?php bloginfo('stylesheet_url'); ?>
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />

You guessed it, these scripts get the settings from the database. Now let’s face it: how often would you change your blog name, or the language, or the style sheet URL, or the HTML charset? For me, it’s once and for all. vi-VN is my site lang, charset is of course UTF-8, and I don’t have any intention to change them ever. That’s why in the theme, I replaced the dynamic scripts with static content whenever applicable:

<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="vi-VN">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="http://static.thica.net/css/notepad-chaos.css?ver=1.2.21" type="text/css" media="screen" />
<link rel="pingback" href="http://www.thica.net/xmlrpc.php" />
<!-- and so forth -->

This way I saved quite a few of unnecessary queries and made my site run a bit faster.

4. Follow Yahoo’s optimization tips

Have you taken a look at Yahoo!’s Best Practices for Speeding Up Your Web Site? It is an awesome resource for those who want to optimize their blogs for performance. Among the rules, these are particularly useful for my case and have been implemented:

4.1. Add an Expires or a Cache-Control Header

Clock
Original image by laffy4k

An Expires header lets the browser have an idea of when the requested content is expired and needs to be re-downloaded. By setting a content’s expires header to a far future, you can tell the browser to use the local cached copy instead of retrieving a fresh version from the server, thus save both bandwidth and loading time. Perfect candidates for this are the images, css, javascript etc.

In the .htaccess file of Thica.net’s root directory, I added these lines:

<IfModule mod_expires.c>
ExpiresActive on
ExpiresByType image/gif "access plus 10 years"
ExpiresByType image/png "access plus 10 years"
ExpiresByType image/jpg "access plus 10 years"
ExpiresByType application/x-javascript "access plus 10 years"
ExpiresByType text/css "access plus 10 years"
</IfModule>

These lines mean “These images, javascript, and css includes will not be changed for 10 years more, so dear Firefox/Chrome/Opera/Safari/IE, please use their copies from your cache whenever applicable and don’t put the heavy load on me, thanks”. The so understanding browser will be ok with such a polite request, and tada, all the specified contents are loaded from the cache in a blink of an eye.

4.2 Gzip Components

Zip
Original image by Isobel T

Now-a-days, all modern browsers support gzipped components. Imagine it like this: first the browser requests for a page. Instead of returning the page as is, the server compresses it and sends the archive back. The browser receives the archive, decompresses it into normal state, and renders the decompressed content normally. Like WinZIP or WinRAR does, but in a web context. Simple?

To take advantage of this technique, once again I opened the .htaccess file and added these lines:

<ifmodule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript
</ifmodule>

This configuration forces the server to gzip those MIME contents before returning them to the browser. Made a quick test at the GIDZipTest fot the homepage and I received this result:

Web page compressed? Yes
Compression type? gzip
Size, Markup (bytes) 31,179
Size, Compressed (bytes) 7,476
Compression % 76.0

So, 3 lines added into the .htaccess file and I reduced 76% of bandwidth (means loading time cut down to 24%). Marvelous.

4.3 Split Components Across Domains

Servers
Original image by Jamison_Judd

Browsers have a limit on how many parallel requests can be sent - it’s 2 for Internet Explorer and 4 for Firefox (configurable, but can’t exceed 8 if I’m not wrong). This is a per domain value. It is advised that a site’s components should be distributed on more than one domain to maximize the parallel downloads. So if your HTML is served from site.com, your images are located on img.site.com, and your css files are put on static.site.com, the number of maximum parallel downloads a browser can perform on your site are tripled, and the loading time may be cut by two third or so.

That’s why I created two subdomains: img.thica.net for the theme images, and static.thica.net for other static contents like style sheets and javascripts. The performance is significantly improved - my site often finishes loading before I knew it, period.

The result so far

Well, my site ran much faster. Unfortunately, the errors kept occurring from time to time still. From the error logs, it showed that somehow my php5 CGI processes were terminated now and then, hence the 503 and 404 errors.

I contacted my host. They said my site was using too much of resource. I told them that a WP-powered site with 2K to 3K of views per day and 2GB of bandwidth a month could hardly use too much resource. So they were like: bandwidth and resource are not the same. Then they blamed my PHP scripts, saying that All in One SEO Pack sucked. “Then how come it’s so widely used around this earth?” I asked. They kept silence, the errors kept happening.

I was forced to use my final weapon.

5. Switch to another host

WPWebHost

Yes, the final step I took was switching to another host. I asked for reference from many people, and later got convinced by Jean Baptiste Jung, the famous guy behind WPRecipes, CatsWhoCode, and most recently CatsWhoBlog, to go with WPWebHost (many thanks, Jean!). It was not a smooth migration to be honest, as I had 4 or 5 sites to be relocated, when my old host doesn’t use cPanel for site controlling. But what I do really, really appreciate is, no matter what the problem was, no matter small or big, they were always there, supportive and helpful.

Well I don’t want to sound like a salesman, but WPWebHost really rocks. So if you are planning for a move, I highly recommend them. The banner above is in fact an affiliate link, so I would appreciate a lot if you purchase their hosting package via clicking on it ;)

The final result

That’s it - my journey to optimize my Thica.net to make it speedy, and I’m really pleased with the result: faster load, light footprints, no stupid errors, minimum bandwidth. You may want to check the result yourself at the site itself. What do you think about it / this article / my pidgin English / my bad writing? I’m happy to see your comments.


  • Thanks for this tips. Although it’s a long entry but I got a lot of knowledge here.

  • Your site loads very fast!
    What changed from that time to today?

  • Nothing much… I guess it’s the host.

  • You didnt found anything better to speedup wordpress?
     
    Well, I have some suggestions, there is a way to speedup by using .htaccess.
    http://wordpress.org/extend/ideas/topic/wordpress-performance-improvement-that-does-not-require-a-plugin-simple-fix#post-14735

  • Oh my God… so it is you who builds thica.net? Don’t tell me that you come up with lacai.org too…
    My respect is all yours, sir. Those are the two sites that I frequent the most, and not in a million years could I expect them to be built by one man. Good job!

  • Thanks for the compliments Anh. Yeah I built and manage the two sites (and some more out there, but for personal purpose only).

  • nice tips on using the .htaccess and you site is very fast to load. I will be using few of these on my site.
    Thank you.

  • These are some great tips for speeding up your WordPress blog. I too would recommend deleting any unused plugins from your installation to speed it up. Our WordPress servers are very fast anyway but we always recommend that our clients delete unusued plugins and also keep the amount of plugins they have installed to a minimum to maximize the speed at which their pages load.

You can follow any responses to this entry through the RSS 2.0 feed.