In Ehcache 2, it was possible to get the size in memory using calculateInMemorySize() e.g.:
CacheManager manager = CacheManager.create();
Cache cache = new Cache(
new CacheConfiguration("test", 100)
.eternal(true)
.statistics(true));
manager.addCache(cache);
assertEquals(0, cache.calculateInMemorySize());
cache.put(new Element(0, "A"));
cache.put(new Element(1, "B"));
cache.put(new Element(2, "C"));
assertTrue(cache.calculateInMemorySize() > 0);
manager.shutdown();
What is the equivalent in Ehcache 3.6.1?
In the following, the getOccupiedByteSize() method returns -1:
StatisticsService statisticsService = new DefaultStatisticsService();
CacheManager manager = CacheManagerBuilder.newCacheManagerBuilder()
.using(statisticsService)
.build(true);
CacheConfiguration<Integer, String> config =
CacheConfigurationBuilder.newCacheConfigurationBuilder(
Integer.class, String.class, ResourcePoolsBuilder.heap(100))
.withExpiry(ExpiryPolicy.NO_EXPIRY)
.build();
Cache<Integer, String> cache = manager.createCache("test", config);
cache.put(0, "A");
cache.put(1, "B");
cache.put(2, "C");
CacheStatistics stats = statisticsService.getCacheStatistics("test");
TierStatistics heap = stats.getTierStatistics().get("OnHeap");
assertTrue(heap.getOccupiedByteSize() > 0);
manager.close();
It does work for a memory unit limited cache. e.g. when the cache configuration is:
CacheConfiguration<Integer, String> config =
CacheConfigurationBuilder.newCacheConfigurationBuilder(
Integer.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, MemoryUnit.MB))
.withExpiry(ExpiryPolicy.NO_EXPIRY).build();
This is not desirable as the cache must be configured with an element limit, not a memory limit.
As per Henri's answer below, it is possible to get the memory size using Sizeof.deepSizeOf(), however some knowledge of the cache implementation is required to exclude unwanted objects e.g.:
SizeOfFilter ehcache = new SizeOfFilter() {
@Override
public Collection<Field> filterFields(Class<?> klazz, Collection<Field> fields) {
if (EhcacheBase.class.isAssignableFrom(klazz)) {
for (Field field : fields) {
if ("store".equals(field.getName())) {
return Collections.singletonList(field);
}
}
return Collections.emptyList();
}
return fields;
}
@Override
public boolean filterClass(Class<?> klazz) {
return true;
}
};
SizeOf sizeOf = SizeOf.newInstance(ehcache);
long size = sizeOf.deepSizeOf(cache);
There is an enhancement request to simplify it here: https://github.com/ehcache/ehcache3/issues/2500
It's not possible. By design.
We do not calculate size when the limit is entries. For performance reason. Keeping track of the size is quite costly.
However, I think in your case, I would do a sizeof. If you don't need it that often, just do a sizeof of the cache and it will give you the current cache size nicely.
SizeOf sizeOf = SizeOf.newInstance();
long deepSize = sizeOf.deepSizeOf(cache); // in bytes