如何使用可用 RAM 在 Java 中高效地缓存对象?

2022-09-01 17:52:01

我需要使用任何可用RAM的比例在Java中缓存对象。我知道其他人已经问过这个问题,但没有一个回答符合我的要求。

我的要求是:

  • 简单轻便
  • 不比普通的哈希图慢得多
  • 使用 LRU 或一些近似于 LRU 的删除策略

我尝试了LinkedHashMap,但是它要求您指定最大数量的元素,并且我不知道需要多少元素才能填满可用的RAM(它们的大小会有很大差异)。

我目前的方法是使用Google Collection的MapMaker,如下所示:

Map<String, Object> cache = new MapMaker().softKeys().makeMap();

这似乎很有吸引力,因为它应该在需要更多RAM时自动删除元素,但是存在一个严重的问题:它的行为是填满所有可用的RAM,此时GC开始崩溃,整个应用程序的性能急剧下降。

我听说过像EHCache这样的东西,但它对于我需要的东西来说似乎很重,我不确定它对于我的应用程序来说是否足够快(请记住,解决方案不能比HashMap慢得多)。


答案 1

我有类似的要求 - 并发(在2个六核CPU上)和LRU或类似 - 并且还尝试了Guava MapMaker。我发现softValues()比weakValues()慢得多,但是当内存填满时,两者都使我的应用程序变得非常慢。

我尝试了WeakHashMap,它的问题更少,奇怪的是,它甚至比通过其demoveEldestEntry()方法使用LinkedHashMap作为LRU缓存更快。

但对我来说最快的是ConcurrentLinkedHashMap,它使我的应用程序比我尝试过的任何其他缓存快3-4(!!)倍。喜悦,经过几天的挫折!它显然已被纳入番石榴的MapMaker,但无论如何,LRU功能都不在番石榴r07中。希望它对您有用。


答案 2

我已经实现了serval缓存,它可能与实现新的数据源或线程池一样困难,我的建议是使用jboss缓存或其他众所周知的缓存库。所以你会睡得很好,没有问题