Java 如何让Ehcache保留无界缓存的堆大小字节统计信息?

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

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

经历了这些之后,我想,“如果花这么长的时间给我堆大小统计信息,
maxBytesLocalHeap
缓存设置到底是如何工作的?”下面看到的我的缓存并没有设置
maxBytesLocalHeap
,而是设置了
maxElementsInMemory
设置。因此,我决定改用
maxBytesLocalHeap
设置,瞧,现在需要大约1毫秒的时间来获取统计数据

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

是否有人知道如何让Ehcache即使在未使用
maxBytesLocalHeap
缓存设置时也保持堆大小统计信息

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

我开始认为我所要求的东西在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();
}
稍后,使用
net.sf.ehcache.store.MemoryStore.MemoryStore(ehcache、pool、BackingFactory、SearchManager)从此池创建
net.sf.ehcache.store.MemoryStore
。以下几行创建
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));
}
由于池是一个无界池(未指定堆大小),因此创建的
PoolAccessor
没有
net.sf.ehcache.pool.SizeOfEngine
,但更重要的是类型是
net.sf.ehcache.pool.impl.UnboundedPool.unbounddpool.unbounddpoolaccessor
。此类型的add方法不跟踪大小,而为有界池创建的PoolAccessor类型跟踪大小。(请参见
net.sf.ehcache.pool.impl.AbstractPoolAccessor.add(对象、对象、对象、布尔值)

因此,我很不走运,因为Ehcache有一个我可以使用的设置,但是,如果像我一样,您正在寻找一个无限缓存,那么有一种黑客方法可以实现这个解决方案。下面将在添加内存统计信息时跟踪这些信息,但将允许对缓存进行无限制的添加:

<cache name="myCache"
    timeToIdleSeconds="1800"
    memoryStoreEvictionPolicy="LRU"
    overflowToDisk="false"
    overflowToOffHeap="false"
    maxBytesLocalHeap="1">
    <pinning store="inCache" />
</cache>

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