implements Elegance {

// Elwyn Malethan's musings on software development, mountain biking and general navel–gazing...

Caching

By changing the layout of my site the other day I caused myself some problems. I knew that my markup processing code – that translates a combination of textile formatted text with embedded source fragments – was a tad inefficient. I rolled my own processor that uses Textile4J to process the text with an added filter-style system for the source fragments, formatted with JHighlight. So a fragment of this page may look like this:

I know have one with some extra functionality. Namely the option to cache the output of the markup 
processor so that any subsequent call to the same tag–library with the same value will use 
the cached version.

<textfu:jhighlight language="xml">
<tf:out value="${blogPost.body}" engine="textile" useCache="true"/>
</textfu:jhighlight>

_Voila!_ Faster loading pages and a much happier VPS(Virtual Private Server).

h2. Caching implementation

I knew it was inefficient but it was brought home quite how inefficient yesterday.

The day before yesterday I changed the way my site is laid out so that there is more content on the home page and the listing pages. No more excerpt or intro text, straight to the main article. This meant that my cobbled together – or mashed up perhaps (makes it sound cool rather than stupid) – markup processor was doing a lot more work per request.

It may be a coincidence but my Gandi–hosted virtual server bombed yesterday. Happy to accept that I may have been to blame, I concluded that I should at least eliminate the code from my enquiries.

Incidentally, Gandi have still not responded to the support ticket I raised yesterday. As my friend Keeran quite rightly put it:

[Gandi] has potential to be huge (because of the pricing), but if the support is that weak they‘re going to FAIL.

Caching

The solution I came up with isn‘t ideal and I haven‘t given much thought to best–practice or the design that much.

I have this additional code in my tag–library class. And yes, I called my markup processor Textfu. I thought for ages about a suitable, meaningful and succinct name for it. In the end I failed, so Textfu had to do. I wonder if the inventor of attachment_fu went through the same process and ended up just settling on that name.

String html;
if (useCache) {
    log.debug("Using CacheFu");
    String key = new BASE64Encoder().encode(MessageDigest.getInstance("MD5").digest(bodyText.getBytes()));
    if(CacheFu.get(key) != null) {
        log.debug("Found cached string for key " + key);
        html = CacheFu.get(key);
    } else {
        log.debug("No value found in cache for " + key);
        html = TextFuFactory.getProcessor(engine).decorate(bodyText);
        CacheFu.put(key, html);
    }
} else {
    html = TextFuFactory.getProcessor(engine).decorate(bodyText);
}

Where before I had a tag–library that read the following:

<tf:out value="${blogPost.body}" engine="textile" />

I know have one with some extra functionality. Namely the option to cache the output of the markup processor so that any subsequent call to the same tag–library with the same value will use the cached version.

<tf:out value="${blogPost.body}" engine="textile" useCache="true"/>

Voila! Faster loading pages and a much happier VPS.

Caching implementation

I am uncertain as to whether what I‘ve implemented is a suitable solution for any large scale project or whether it‘s a big no no in terms of best–practice. It seems to be working well for my site in any case. If what I've done has any flaws, please let me know. Note the imaginative name of the class again.

package com.malethan.blog.textfu.taglib;

import java.util.Map;
import java.util.HashMap;

public class CacheFu {
    //----------------------------------------------------------------------- Static Properties and Constants

    private static ThreadLocal<Map<String,String>> LOCAL_CACHE = new ThreadLocal<Map<String, String>>();

    //----------------------------------------------------------------------- Static Methods

    public static String get(String key) {
        return getCache().get(key);
    }

    public static void put(String key, String value) {
        getCache().put(key, value);
    }

    private  static Map<String, String> getCache() {
        if (LOCAL_CACHE.get() == null) {
            LOCAL_CACHE.set(new HashMap<String, String>());
        }
        return LOCAL_CACHE.get();
    }

}

First published on Jan 28, 2009. Last updated on: Jan 29, 2009.

Comments (0)

Leave a reply »

 

Leave a Reply

Your name
 
Email
 
Website
 
Comment

You may use Textile notation here
 
 

Please perform this simple arithmetic test to prove you are human
 
 
 
People I like
Other sites