Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Can I Get Ehcache To Keep Heap Size Bytes Statistics For Unbounded Caches?

Tags:

java

ehcache

I'm using Ehcache (version 2.7.1) and would like to periodically retrieve stats such as number of elements in the cache and the size of the cache in bytes. The problem that I'm running into though is that using net.sf.ehcache.statistics.StatisticsGateway.getLocalHeapSizeInBytes() (StatisticsGateway retrieved by calling net.sf.ehcache.Ehcache.getStatistics()) takes a very long time with 15000 elements with a total size of about 536MB. In one example on my local machine, it took over 21 seconds to get this statistic.

After I experienced this I thought, "How in the world does the maxBytesLocalHeap cache setting work if it takes this long to give me the heap size stats?" My cache, seen below, did not set the maxBytesLocalHeap, but rather the maxElementsInMemory setting. So, I decided to use the maxBytesLocalHeap setting instead and voila, now it takes about ~1ms to get me the stat.

So it seems very likely that Ehcache is not saving statistics on heap size if the cache does not use the maxBytesLocalHeap setting. Instead, it's computing the size of every object again and again for every call I make for that stat. I would like these stats though, I just don't want to use them as part of an eviction policy. So I then tried to set statistics="true", however I still am not getting my heap size stats back any faster. I've tried searching Ehcache documentation to find an answer and even looked through the ehcache.xsd for settings that I'm potentially missing, but I didn't find anything relevant.

Does anyone know how to get Ehcache to keep heap size statistics even when the maxBytesLocalHeap cache setting is not used?

<cache name="myCache"
    timeToIdleSeconds="1800"
    overflowToDisk="false"
    memoryStoreEvictionPolicy="LRU"
    diskPersistent="false"
    maxElementsInMemory="0"
    statistics="true"/>
like image 278
butallmj Avatar asked Nov 07 '13 16:11

butallmj


1 Answers

I'm beginning to think what I'm asking for isn't possible with Ehcache (at least the version I'm on)

Here is the pool config in the source for net.sf.ehcache.Cache.class:

// on-heap pool configuration
Pool onHeapPool;
if (configuration.getMaxBytesLocalHeap() > 0) {
    PoolEvictor evictor = new FromLargestCachePoolEvictor();
    SizeOfEngine sizeOfEngine = cacheManager.createSizeOfEngine(this);
    onHeapPool = new BoundedPool(configuration.getMaxBytesLocalHeap(), evictor, sizeOfEngine);
} else if (getCacheManager() != null && getCacheManager().getConfiguration().isMaxBytesLocalHeapSet()) {
    onHeapPool = getCacheManager().getOnHeapPool();
} else {
    onHeapPool = new UnboundedPool();
}

Later on a net.sf.ehcache.store.MemoryStore is created from this pool, using net.sf.ehcache.store.MemoryStore.MemoryStore(Ehcache, Pool, BackingFactory, SearchManager). The following lines create the net.sf.ehcache.pool.PoolAccessor:

if (pool instanceof UnboundedPool) {
    this.poolAccessor = pool.createPoolAccessor(null, null);
} else {
    this.poolAccessor = pool.createPoolAccessor(new Participant(),
        SizeOfPolicyConfiguration.resolveMaxDepth(cache),
        SizeOfPolicyConfiguration.resolveBehavior(cache).equals(SizeOfPolicyConfiguration.MaxDepthExceededBehavior.ABORT));
}

Since the pool is an UnboundedPool (no heap size was specified), the PoolAccessor is created without a net.sf.ehcache.pool.SizeOfEngine, but more importantly the type is net.sf.ehcache.pool.impl.UnboundedPool.UnboundedPoolAccessor. The add method for this type does not track size, while the type of PoolAccessor that's created for for a bounded pool does. (see net.sf.ehcache.pool.impl.AbstractPoolAccessor.add(Object, Object, Object, boolean)).

So, I'm out of luck in terms of Ehcache having a setting that I can use, however there is a hacky way to achieve this solution if, like myself, you are seeking an unbounded cache. The below will keep track of memory stats as they are added, but will allow unbounded additions to the cache:

<cache name="myCache"
    timeToIdleSeconds="1800"
    memoryStoreEvictionPolicy="LRU"
    overflowToDisk="false"
    overflowToOffHeap="false"
    maxBytesLocalHeap="1">
    <pinning store="inCache" />
</cache>
like image 56
butallmj Avatar answered Oct 24 '22 09:10

butallmj