任何可以限制内存缓存的内存使用的Java缓存,而不仅仅是实例计数?

时间:2009-03-27 17:51:01

标签: java caching memory-management ehcache

我正在寻找一个简单的内存(和进程中)缓存,用于查询数据的短期缓存(但短期意义超出请求/响应,即会话边界)。 EhCache可能会工作,但看起来好像它可能不提供我需要的东西:限制不是缓存的对象数量,而是(近似)限制缓存数据消耗的内存量。

据我所知,很难在没有序列化的情况下找出给定对象的确切内存使用情况(我希望在一般情况下避免因为它的速度慢而无法使用我的目的),并且我很好地提供了大小估计自己。

那么:是否有一个简单的开源java缓存,允许定义缓存对象的“权重”,以限制缓存的内容量?

EDIT(2010年11月):对于它的价值,有一个名为Java CacheMate的新项目试图解决这个问题,以及其他一些改进的想法(多级内存中进程内缓存)

8 个答案:

答案 0 :(得分:3)

我同意保罗的说法,这通常是通过使用软参考缓存来解决的,尽管它可能比您更喜欢早于条目。通常可接受的解决方案是使用驱逐到软缓存的普通缓存,并在可能的情况下恢复未命中的条目。这种受害者缓存方法非常有效,如果有可用内存,可以提供更低的标准,但可以获得额外的好处。

可以通过启用Java代理来确定内存大小,并且在使用SizeOf实用程序(http://sourceforge.net/projects/sizeof)时使用非常简单。我只是将它用于调试目的,我建议在将其用于正常使用之前对开销进行基准测试。

在我的缓存库中,我计划在实现核心算法后添加插入评估程序的功能。这样,您可以将集合存储为值,但将缓存绑定为所有集合大小的总和。我已经看到无限集合,因为缓存中的值会导致OutOfMemoryExceptions,因此控制非常方便。

如果您真的需要这个,我建议不要这样做,我们可以增强当前的实现来支持这一点。你可以给我发电子邮件,ben.manes-at-gmail.com。

答案 1 :(得分:2)

如何使用启用了LRU算法的简单LinkedHashMap并将所有数据放入其中的SoftReference ...例如cache.out(key,new SoftReference(value))??

这会将缓存限制为可用内存量但不会终止程序的其余部分,因为Java会在有内存需求时删除软引用...不是全部...最旧的第一个...通常。如果向实现添加引用队列,还可以从映射中删除停顿条目(仅键,无值)。

这将使您无需计算条目的大小并跟踪总和。

答案 2 :(得分:2)

EhCache V2.5目前提供的解决方案可以根据缓存的内存大小进行限制。有关详细信息,请结帐EhCache 2.5 Documentation

答案 3 :(得分:0)

这不仅难以衡量 - 很难定义。

假设两个缓存条目引用相同的字符串 - 它们两者计算该字符串的大小,尽管从缓存中删除它们中的任何一个都不会使该字符串符合垃圾条件采集?他们都没有计算大小,尽管如果这两个从缓存中移除,那么字符串可能有资格收集?如果不在缓存中的另一个对象具有对该字符串的引用呢?

如果你可以准确地描述你感兴趣的大小可以以编程方式确定它 - 但我怀疑你甚至很难确定你想要的确切内容。

答案 4 :(得分:0)

除了猜测对象的内存使用情况之外,对于合理的算法,您还需要猜测重新创建它的成本。一个合理的猜测是娱乐成本大致与内存大小成正比。因此,这些因素相互抵消,你也不需要。一个简单的算法可能会更好地解决。

答案 5 :(得分:0)

如果您无法进行任何估算 - 编写一个缓存驱逐策略,该策略根据JVM堆大小(从系统轮询)刷新或由finalize()触发 - 从孤立对象(在GC上)调用。

答案 6 :(得分:0)

可以为缓存的内存使用量定义有意义的度量。您可以计算:"retained size"。 不幸的是,计算保留的大小与完整GC一样昂贵,因此可能不是一种选择。在某些JVM语言(clojure?)中,理论上可以确保缓存中的对象不会从外部对象引用,然后您可以监视缓存的实际大小。

答案 7 :(得分:-1)

完成这项工作的是java.lang.ref.SoftReference。通常,您扩展SoftReference类,以便子类包含密钥。