5

我有一个计算密集型的一次性离线处理任务,需要我几个小时才能运行,并且我使用咖啡因作为我的内存缓存。设置最大缓存大小的好方法是什么?我正在用 8GB 的​​ RAM 运行我的 Java 程序,我愿意提供大约 4GB 的缓存,但我不确定内存如何转换为我的缓存整体的实际大小。我决定.softValues()让 JVM 决定,但我在 Caffeine 的 JavaDoc 中遇到了以下单词:

警告:在大多数情况下,最好设置每个缓存的最大大小,而不是使用软引用。仅当您非常熟悉软引用的实际后果时,才应使用此方法。

4

2 回答 2

13

软引用在概念上很有吸引力,但通常会损害长时间运行的 JVM 的性能。这是因为它们通过填满老年代产生堆压力,并且仅在完整 GC 期间被收集。这可能会导致 GC 颠簸,每次释放足够的内存时,它会很快被消耗,并且需要另一个完整的 GC。对于延迟敏感的应用程序,这会受到进一步影响,因为驱逐是全局的,因为没有办法提示哪些缓存是最关键的。

软引用不应该是默认的,去策略。在吞吐量、非面向用户的任务中,这可能是一个合理的简化。但是当 GC 时间、延迟和可预测的性能很重要时,它就很危险了。

不幸的是,大小的最佳答案是猜测、测量和重复。导出统计数据,尝试设置并适当调整。命中率曲线可以通过捕获访问轨迹(key hash 的日志)并用不同的大小对其进行模拟来获得。它的数据很有趣,但通常一些简单的调整运行就足够了。

于 2016-09-15T05:03:19.353 回答
3

软引用允许 VM 在内存不足时回收对象。这在某种程度上是与缓存不同的策略。你可以简单地有一个(但是和WeakHashMap之间有区别)SoftReferenceWeakReference

一个很大的区别是缓存通常让您决定驱逐对象(lru、fifo 等)的策略,而软/弱引用不会。

你至少应该能够猜出一个物体的大小。是 1k、1mb、10mb 吗?

如果你真的不知道你的对象有多大,大多数缓存允许你添加一个监听器来驱逐并记录它。结合查找时缓存未命中的日志,您应该可以很好地了解缓存的执行情况。

于 2016-09-15T04:51:01.613 回答