21 November 2013

Digging into EHCache (and TTL)

Using a caching frameworks (like Grails Cache and Grails EhCache) instead of writing the caching mechanism yourself is comfortable. You find yourself smacking @Cacheable on listing operations and get methods - and CacheEvict on the CRUD operations. Right?

But this is extremely distant from the actual implementation - so I think it's a good idea to have a close look and confirm it works as you think.

So let's investigate, using 2 techniques achieving 3 goals.

Goals are:
1. Confirming Configuration run-time
2. Watching the Cache run-time
3. Confirming TTL timers in run-time
4. Unit testing

Techniques described:
1. JMX
2. Grails Console Plugin

First you need to verify that EhCache is JMX exposed. I have this in Bootstrap.groovy.

Then, fire up jConsole

Confirming configuration

EhCache works "great" without any configuration at all - and then runs purely on defaults - which can trick you to believe your system works as you configured.

So let's see that the configuration you intended are correct. We do this by browsing in jConsole to "net.sf.ehcache" -> "CacheConfiguration" and click the cache name.

I've now verified my cache TTL has the exact value 1800 seconds (aka 30 minutes), matches my config file. Meaning my config file works.

Watching the Cache run-time

Head over to CacheStatistics in jConsole, and watch for CacheHits and CacheMiss

CacheHit means the cache did its job and returned cached results instead of invoking the annotated method. CacheMiss means the method was invoked. A high number on CacheHits is probably a sign of a healthy set up.

Confirming TTL timers
This may seem uneccesary, but I wanted to look at how this worked, so I dug into it. I couldn't find the TTL timers exposed in JMX, so I dug into the runtime using Grails Console Plugin.

So grab the CacheManager, find your cache, and ask for ExpirationTime and Creation Time.

This code on Gist

As you see, there is a perfect 30 minutes between Expiration and Creation time. Perfect.

Now sit back and wait until the ExpirationTime passes - and watch a new CacheMiss increasse in jConsole! If it does, everything is working as you intented.

Unit testing
This kind of configurations doesn't feel like a good fit for unit testing in my book. But maybe I'm wrong.