The Hungry Hacker's Explanation of Everything

Home » Software

Super-caching with TimThumb

23 April 2010 7 Comments

This website doesn’t actually use TimThumb – our hack of the Arthemia theme instead uses Flickr for all it’s image hosting, so it’s just easier to hack the theme to understand how to pull different sizes of Flickr images instead.

However, we have another site that my wife’s internet services company hosts that needed to be optimized for Digg/Slashdot-style surges, and it does use TimThumb – extensively in fact.

The Problem

TimThumb does have a caching engine built in which will, if your permissions are set up correctly, prevent the thumbnail from having to be re-generated each request. However, it does require the PHP script to run each time to return the cached file (in fact, the PHP script simply takes all the arguments, concatenates them together, generates an MD5 hash, then looks for that file).

If you’re using mod_php, this probably isn’t a huge deal… it’s not going to be the bottleneck for surges of traffic – mod_php and your heavy-weight Apache processes will be. If you’re using php-cgi or php-fcgi, however, having quite a few thumbnails on the page (such as themes like Arthemia) is going to cause you quite a headache. You could have at least 10 or 15 extra php processes per page load… even required to just answer an If-Modified-Since request!

Proposed Solution: Hack TimThumb

I don’t know if this is the greatest idea, but it seems to work. Our idea was simply to make TimThumb cache files in the same manner that Donncha’s WP-Super-Cache plugin does, and then the web server can simply fling out pre-thumbnailed images all day long without invoking php at all.

The first thing we had to do was modify TimThumb to save cached thumbnails in this manner, for which you can find a rough patch here:

It’s not perfect, because it requires you to edit the script and point it at your thumbnails directory. We made ours /thumbs in the website’s root directory, and you have to point it at the operating system’s fully-qualified path to that directory. We then saved the modified version of the script into our /thumbs/ directory so we could access it easily.

The format is then /thumbs/<width>/<height>/<path/to/image>. A quick check of the file system shows it’s caching the files properly and finding the cached versions okay. Now to remove PHP from the equation.

Rewrite Rules

%cat .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([0-9]+)/([0-9]+)/(.+)$ /thumbs/timthumb.php?src=$3&w=$1&h=$2&zc=1&q=100 [L]

I stole this rewrite rule from WP-Super-Cache, basically it just checks if the file isn’t a file, and it isn’t a directory, and then passes it in an argument to TimThumb. You can edit the zoom/crop and quality settings globally here – if you want them adjustable on a per-image basis you’ll need to hack the script to include those in the cache path instead.

If the file exists (which it will, if it’s been cached) Apache can simply pass that file out as a static file, PHP is never invoked for that image. When combined with nginx as a reverse proxy, we’ve found this resulted in a dramatic increase in performance for just one page-view alone. Because of our WP-Super-Cache rules for nginx will also work for these cached images, nginx can hand out upwards of around 7,000 thumbnails a second – more than enough to saturate a gigabit pipe on reasonable hardware.

Editing the Theme

Next up is editing the theme to call our new thumbnail URL – unfortunately, there’s no way around this process… it’s tedious. Replace:

<p><img src="<?php echo bloginfo('template_url'); ?>/scripts/timthumb.php?src=<?php echo get_option('home'); ?>/<?php
$values = get_post_custom_values("Image"); echo $values[0]; ?>&amp;w=<?php echo $width; ?>&amp;h=<?php echo $height; ?>&amp;zc=1&amp;q=100"
alt="<?php the_title(); ?>" width="<?php echo $width; ?>px" height="<?php echo $height; ?>px"  /></p>

with:

<p><img src="/thumbs/<?php echo $width; ?>/<?php echo $height; ?>/<?php
$values = get_post_custom_values("Image"); echo $values[0]; ?>"
alt="<?php the_title(); ?>" width="<?php echo $width; ?>px" height="<?php echo $height; ?>px"  /></p>

Caveats

There are a couple of downsides to this… first of all, there’s no automatic garbage collection. I don’t suppose it’s that big of a deal, because realistically you’re probably going to want to keep the thumbnailed images around anyway.

As mentioned above, unless you want to hack your URL scheme to include those arguments – you lose the ability to control the quality and the zoom/crop arguments on a per-image basis.

Related Links

7 Comments »

  • Hema Latha said:

    Hi Fwaggle,

    I read this article many times, but couldn’t figure out how to implement the steps you have mentioned above. Recently moved to HostGator and having issues keeping my site online as there are issues with timthumb.

    Is it possible for you to fix this issue for me?

    Thank you.

  • fwaggle (author) said:

    Send me an email @hungryhacker.com with details about the bits you’re having trouble with and I’ll see what I can do.

  • Optimizing WordPress For Shared Hosting • Return True said:

    […] thanks to speedingupwebsite.com & also thanks to hungryhacker for the code here. I’ve modified it (very slightly) as while it was very helpful it just […]

  • Jessica said:

    Thanks for the info. What version of timthumb did you use?

  • fwaggle (author) said:

    Sorry about the delay in responding – I honestly have no idea what version it is. It’s whatever version was bundled with the Arthemia theme we hacked up. 🙁

  • Silas Mariusz said:

    Hi!

    Can you please attach timthumb version required for this patch. It seems to be too old for current timthumb build.

    Thanks!

  • fwaggle (author) said:

    Hey, sorry about that – I don’t actually have it any more. 🙁 We were just using whatever came with the Arthemia theme back around the time the article was written.

Leave your response!

Add your comment below, or trackback from your own site. You can also subscribe to these comments via RSS.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This is a Gravatar-enabled weblog. To get your own globally-recognized-avatar, please register at Gravatar. Note: By filling out this comment form or emailing us you are signifying that you have read and agree to the terms laid out on the Contact Us page.