google common cache – maximumSize的默认值(和其他“可选”设置) – 想要一个使用所有“可用”内存的缓存

我刚刚通过搜索缓存API找到了Guava (它非常适合我的需求)。 但是在阅读wiki和Javadoc时出现了一个问题 – CacheBuilder可以采用什么设置的默认值? Javadoc声明“这些function都是可选的”和“使用默认设置构造一个新的CacheBuilder实例,包括强键,强值,并且不会自动驱逐任何类型。”

在我看来, maximumSize一个很好的默认值是相对于Runtime.getRuntime().freeMemory();

最后,我想要一个使用给定系统上可用内存的缓存。 所以我需要一个驱逐策略,询问freeMemory()有多少可用(可能相对于Runtime.getRuntime().maxMemory()

我让我质疑同样的事情,在网上找不到任何东西。 所以我做了这个非常原始的测试。 我编写了一段代码,创建了一个具有最基本设置的LocalCache(没有最大大小,没有驱逐策略,没有),并且在无限循环中将内容放入缓存中。 并通过VisualVm监视它以检查堆使用情况。

 import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import java.util.concurrent.TimeUnit; public class CacheTest { public static void main(String[] args) { Cache cache = CacheBuilder.newBuilder().build(); int counter = 0; while(true){ cache.put("key"+counter++,"value"); System.out.println("size:"+cache.size()); } } } 

从下图中可以看出,内存使用量增长到最大可用空间并变为常量。 我等了几分钟,没有出现OutOfMemoryError。 发生的事情是,几秒钟之后,一个新条目被添加到地图中,因此将来可能会出现错误。

堆转储

结论:您不必设置maximumSize值,但我建议您使用某种逐出策略(expireAfterAccess或expireAfterWrite)来清理缓存并避免出现OutOfMemoryError。 并且还要避免降低缓存的性能。

实际上,可用内存并不是缓存驱逐度量的最佳选择。 原因是因为垃圾收集。 耗尽空闲内存可能只意味着现在是垃圾收集器运行的时候了,之后你会突然有大量的空闲内存。 所以你不想仅仅因为你有大量的垃圾而从缓存中删除东西。

一种选择是使用softValues() ,但我强烈建议不softValues() ,因为软引用确实会损害生产性能。

正确的做法是仔细选择maximumSize ,它实际上限制了缓存将占用的内存总量。 如果条目占用可变数量的空间,那么您可以使用maximumWeight来对其进行建模。