Statify dynamic images from timthumb

Make images static

Just to remind: we are going through WordPress performance optimization stage 2 (after 3x speed from Stage 1) and focusing on decrease of number (or payload) of HTTP requests. Last several posts were devoted to CSS images optimization. We reduced their number and reviewed some well-known techniques to perform this automatically (or semi-automatically).

Before we start with actual HTML images distribution through multiple hosts (yes, it’s the most powerful technique here) we need to prepare our thumbnail library – timthumb – to be more fast and reliable.

Why dynamic images are evil?

Frankly speaking it’s very convenient – to upload only one image to the website and create thumbnails of any size from it. But let’s reveal this anti-pattern of web performance optimization. For this image (from the last post)

CSS Sprites challenges

We have the following timings (get by webo.name).

Timings for static image

Here we have about 12ms – it’s too much (but we remember – we are working on a weak shared hosting, it’s a miracle that website can load so fast here) for server side expenses. And for a dynamic equivalent for this static image we have the following figure.

Dynamic image timings

It’s about 8ms difference. It’s not so much, isn’t it? Really? :) For the home page we have 3 large dynamic images (slide show) and 3 smaller (for the slide show too). 16 images x 8ms = 128ms. It’s still not so much but if we compare these expenses with our home page (and every HTML cached page) timings we can see that dynamic image generation ‘eats’ more than 6x from just HTML document response time.

And with every hit to the home page we lose 130ms (and can’t serve 5x more hits with our shared hosting). Please note – this is about home page, pagination and archives pages (with a lot of thumbnails) only. On single post pages there are only 6 such images – mush less but still 2x losses.

How to fix this?

Well the idea is clear enough. We need to create mnemonic file names for each dynamic image (as you remember we actually enabled their caching on Stage 1). And then just add little rewrite magic to .htaccess (sorry if you are not using Apache, maybe you can create the same rules for nginx, lighttpd, or something else) to check cached thumbnail existence and serve it instead of calling dynamic script.

Starting with timthumb.php

We are going to wp-content/themes/bacipress/ (it’s our timthumb.php actual location – it seems to be in the curent theme folder). Cache files are named like md5 hash. So let’s look for a function md5 whch can perform such transformation.

On the line 338 there is

$cache_file = md5( $cachename ) . '.' . $ext;

It seems it’s what we are looking for.
File name is calculated in these 2 lines (this one and the one above).

$cachename = get_request( 'src', 'timthumb' ) ...
$cache_file = md5( $cachename ) . '.' . $ext;

So we need to change logic of $cachename creation. And remove md5 (because md5 sum calculation with every Apache redirect will be very heavy). These two lines have been transformed to

$filename = preg_replace("@http://[^/]+/(.*)\.$ext$@", "$1", get_request( 'src', 'timthumb' ));
$cachename = $filename . '-' .
	get_request( 'w', 100 ) . '-' .
	get_request( 'h', 100 ) . '-' .
	get_request( 'zc', 1 ) . '-' .
	get_request( '9', 80 );
$cache_file = $cachename . '.' . $ext;

There are several changes:

  • We have added correct file name calculation (from the website root) – and removed from it actual file extension (because we need to add some parameters, and this extension is added a bit lower).
  • We have just added dashes in $cachename for better readability.
  • And we have removed md5 from $cache_file.

So we have replaced initial 2 lines with these 7 ones.

Also we need to change default cache directory to the website root (so all thumbnails will be placed exactly near source files). It’s line 39 in file timthumb.php:

$cache_dir = './';

Please change it to the following one.

$cache_dir = '../../../';

OK. Now all our images are placed regarding there location in the website structure. It’s a half of our optimization.

Finishing with .htaccess

The last part is to add some RewriteEngine magic to our .htaccess. Let’s find there the following strings (in BEGIN WordPress part).

RewriteEngine On
RewriteBase /

The last one can be commented or absent – it isn’t required if we are working with WordPress located in the document root of the website. OK. Please insert here (under these rules) the following lines.

RewriteCond %{SCRIPT_FILENAME} timthumb\.php
RewriteCond %{QUERY_STRING} src=http:\/\/[^\/]+\/(.*)\.(png|jpe?g)&w=([0-9]+)&h=([0-9]+)&zc=([0-9]+)
RewriteCond YOUR_HOME_DIRECTORY/%1-%3-%4-%5-80.%2 -f
RewriteRule .* /%1-%3-%4-%5-80.%2 [L]

This can be a bit complicated but let’s review what they perform. The first one

RewriteCond %{SCRIPT_FILENAME} timthumb\.php

checks if any dynamic image (served via timthumb.php) is requested.

The second one

RewriteCond %{QUERY_STRING} src=http:\/\/[^\/]+\/(.*)\.(png|jpe?g)&w=([0-9]+)&h=([0-9]+)&zc=([0-9]+)

computes GET parameters (from query string) to get image file name, its extension, width, and height. Please note there is no quality parameter. If your images URLs look different (with additional GET parameter) please add it to this rule.

The third one

RewriteCond YOUR_HOME_DIRECTORY/%1-%3-%4-%5-80.%2 -f

checks if there is file with requested name (we create such files after the first request with fixes to timthumb.php described above). Variables (%1, %2, %3, %4, %5) are computed from the second rule (expressions in curly brackets).

Small note: how to get your home directory? Some of WordPress plugins can your this information but you can also create in the website root a file rootdir.php with the following content

<?php echo $_SERVER['DOCUMENT_ROOT'] ?>

and copy its output (after you open it in browser). It will be YOUR_HOME_DIRECTORY. Please don’t forget to delete this file after you get this info.

And the last Rewrite rule

RewriteRule .* /%1-%3-%4-%5-80.%2 [L]

just redirects (internally, without no subsequent redirect – flag [L]) to the end file name. Great.

All this has resulted into less response time.

Statified dynamic images

Not 12ms for the really static file but also not 20ms for dynamic (cached) image.

Conclusion

With quite a few changes in timthumb.php and .htaccess we can gain a bit more performance from our website and get it ready for multiple domains usage (which will be discussed in the next blog post). For the home page actual savings are about 15-20ms, or less than 1% (because all images are load in 3-4 chunks of parallel flows). This improvement can save a bit for dedicated server but for a shared hosting it improves the whole website efficiency (because we save server expenses and can show more pages to our visitors without overload).

VN:F [1.8.0_1031]
Rating: 10.0/10 (2 votes cast)
Statify dynamic images from timthumb10.0102

Related Posts

1 RESPONSES TO Statify dynamic images from timthumb

    Leave a Reply

    MySQL queries: 89 | 0.743s
    Memory used: 14M
    Memory limit: 32M