grails-cache-ehcache plugin in Grails app for caching using @Cacheable annotations

473 Views Asked by At

my situation is that I have Grails 2.1.2 application and want to introduce method level caching using cache plugin and cache-ehcache plugin as an implementation.

My cache is configured to be in memory like this:

  grails.cache.config = {
    cache {
        name 'homePageCache'
        enabled true
        eternal false
        pinning {
            store 'localMemory'
    }
  }

I have a method like this one, that takes only int argument so key generation is not an issue:

  @Cacheable('homePageCache')
  TubeVideoPagingArray findHomePageOfVideos(int pageSize) {

My problem is that I got an java.lang.OutOfMemoryError: Java heap space exception when this method is called. The reason is that ehcache computes the size of object that's going to be put in cache using a class called ObjectGraphWalker, that traverses through object graph and sums the size.

I have set a debug level logging for ehcache and see a HUGE number of lines similiar to these:

2014-04-17 13:27:13,470 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'bigDecimalMultiplier' of class java.text.DecimalFormat
2014-04-17 13:27:13,470 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'digitList' of class java.text.DecimalFormat
2014-04-17 13:27:13,470 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'positivePrefixFieldPositions' of class java.text.DecimalFormat
2014-04-17 13:27:13,470 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'positiveSuffixFieldPositions' of class java.text.DecimalFormat
2014-04-17 13:27:13,470 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'negativePrefixFieldPositions' of class java.text.DecimalFormat
2014-04-17 13:27:13,470 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'negativeSuffixFieldPositions' of class java.text.DecimalFormat
2014-04-17 13:27:13,470 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'currency' of class java.text.DecimalFormatSymbols
2014-04-17 13:27:13,488 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'metaClass' of class org.codehaus.groovy.grails.plugins.converters.codecs.XMLCodec$__clinit__closure1
2014-04-17 13:27:13,491 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'metaClass' of class org.codehaus.groovy.grails.plugins.codecs.URLCodec$__clinit__closure2
2014-04-17 13:27:13,492 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'metaClass' of class org.codehaus.groovy.grails.plugins.codecs.URLCodec$__clinit__closure1
2014-04-17 13:27:13,494 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'metaClass' of class org.codehaus.groovy.grails.plugins.codecs.SHA256Codec$__clinit__closure2
2014-04-17 13:27:13,495 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'metaClass' of class org.codehaus.groovy.grails.plugins.codecs.SHA256Codec$__clinit__closure1
2014-04-17 13:27:13,498 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'metaClass' of class org.codehaus.groovy.grails.plugins.codecs.JavaScriptCodec$__clinit__closure1
2014-04-17 13:27:13,501 DEBUG [org.ehcache.sizeof.ObjectGraphWalker] SizeOf engine walking transient field 'metaClass' of class org.codehaus.groovy.grails.plugins.codecs.MD5BytesCodec$__clinit__closure2

It's obvious that it traverses through a bunch of metaClasses which leads it to other metaClasses ending God knows where..

Ehcache has a mechanism to configure this size of computation described here: http://ehcache.org/documentation/configuration/cache-size#built-in-sizing-computation-and-enforcement

And recently I have found out that since the version 2.8 (I use 2.8.1) there is also a programmatic API for this configuration and you can use this library to set it up: https://github.com/Terracotta-OSS/ehcache-sizeofengine

There is referred an implementation of this size of engine for Groovy that should solve the metaClasses traversing. I have tried it and IMHO it does not work - the core of it is this filter:

public void configure(final Filter filter) {
    filter.ignoreInstancesOf(groovy.lang.MetaClass.class, false);
}

I think that problem is that the metaClass field in groovy objects is not the instance of MetaClass - it's also visible in the logs.

So to raise a question after such a long description:

Does someone encoutered the same issue and solved it somehow?

1

There are 1 best solutions below

1
On

If you use https://github.com/alexsnaps/ehcache-sizeofengine-groovy that should solve your issue.

The unfortunately thing, though, is that it's not in Maven Central so you'll need to build it and publish it your