6

我正在使用 Ehcache(版本 2.7.1)并希望定期检索统计信息,例如缓存中的元素数量和缓存大小(以字节为单位)。我遇到的问题是使用net.sf.ehcache.statistics.StatisticsGateway.getLocalHeapSizeInBytes()(StatisticsGateway 通过调用检索net.sf.ehcache.Ehcache.getStatistics())需要长时间,15000 个元素,总大小约为 536MB。在我的本地机器上的一个示例中,获得此统计信息需要 21 秒。

在我经历了这个之后,我想,“maxBytesLocalHeap如果需要这么长时间才能给我堆大小统计信息,那么缓存设置到底如何工作?” 如下所示,我的缓存没有设置maxBytesLocalHeap,而是maxElementsInMemory设置。所以,我决定改用这个maxBytesLocalHeap设置,瞧,现在大约需要 1 毫秒才能得到统计数据。

因此,如果缓存不使用该maxBytesLocalHeap设置,Ehcache 似乎很可能不会保存堆大小的统计信息。相反,它会一次又一次地为我为该统计数据所做的每次调用计算每个对象的大小。不过,我想要这些统计数据,我只是不想将它们用作驱逐政策的一部分。所以我然后尝试设置statistics="true",但是我仍然没有更快地恢复我的堆大小统计信息。我尝试搜索 Ehcache 文档以找到答案,甚至查看了ehcache.xsd中可能缺少的设置,但我没有找到任何相关的内容。

有谁知道即使maxBytesLocalHeap不使用缓存设置,如何让 Ehcache 保持堆大小统计信息?

<cache name="myCache"
    timeToIdleSeconds="1800"
    overflowToDisk="false"
    memoryStoreEvictionPolicy="LRU"
    diskPersistent="false"
    maxElementsInMemory="0"
    statistics="true"/>
4

2 回答 2

2

我开始认为 Ehcache 无法实现我所要求的(至少我正在使用的版本)

这是源中的池配置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();
}

稍后 anet.sf.ehcache.store.MemoryStore从这个池中创建,使用net.sf.ehcache.store.MemoryStore.MemoryStore(Ehcache, Pool, BackingFactory, SearchManager). 以下行创建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));
}

由于池是 UnboundedPool (未指定堆大小),因此PoolAccessor创建时没有net.sf.ehcache.pool.SizeOfEngine,但更重要的是类型是net.sf.ehcache.pool.impl.UnboundedPool.UnboundedPoolAccessor。此类型的 add 方法不跟踪大小,而为有界池创建的 PoolAccessor 类型会跟踪大小。(见net.sf.ehcache.pool.impl.AbstractPoolAccessor.add(Object, Object, Object, boolean))。

所以,就 Ehcache 而言,我很不走运,因为 Ehcache 有一个我可以使用的设置,但是如果像我一样,你正在寻找一个无限缓存,那么有一种方法可以实现这个解决方案。下面将在添加内存统计信息时跟踪它们,但允许无限添加到缓存中:

<cache name="myCache"
    timeToIdleSeconds="1800"
    memoryStoreEvictionPolicy="LRU"
    overflowToDisk="false"
    overflowToOffHeap="false"
    maxBytesLocalHeap="1">
    <pinning store="inCache" />
</cache>
于 2013-11-07T17:50:48.073 回答
0

@butallmj:向缓存实例添加固定存储会否定 memoryStoreEvictionPolicy。因此,无论您是否使用它,添加到缓存中的任何项目都将始终保留在内存中。相反,我建议使用 maxBytesLocalHeap 配置为定义的缓存提供界限。

于 2014-02-16T12:40:52.150 回答