Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ehcache 3 size in memory

Tags:

ehcache-3

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

like image 551
tanderson Avatar asked Nov 01 '25 13:11

tanderson


1 Answers

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
like image 116
Henri Avatar answered Nov 04 '25 21:11

Henri