根据这些micro benchmarks,事实证明,Caffeine在读取和写入操作上都比Guava cache快。
从API的角度看,它们看起来都非常相似。
实施咖啡因的秘诀是什么?它与Guava缓存有何不同?
我是否可以在咖啡因定时到期的情况下使用预定的执行程序在后台执行适当的维护操作?
答案 0 :(得分:6)
主要区别在于,咖啡因使用环形缓冲区来记录和重播事件,而番石榴则使用ConcurrentLinkedQueue
。目的总是要迁移番石榴,并且开始更简单是有意义的,但是不幸的是,从来没有兴趣接受这些更改。环形缓冲区方法可避免分配,有界(有损)且操作成本较低。
剩余成本归因于设计不匹配。 MapMaker
的原始作者热衷于将软引用作为缓和问题的解决方案,方法是将其交给GC。不幸的是,虽然在微基准测试中看似很快,但由于引起了世界各地的GC颠簸,它在实践中的性能令人震惊。基于大小的解决方案必须适应这项工作,这并不理想。咖啡因针对基于大小的文件进行了优化,并且还获得了改进的哈希表,而番石榴则更优雅地处理了引用缓存。
咖啡因不会创建自己的线程来进行维护或到期。确实将成本降到了commonPool
,这会稍微提高面向用户的延迟,但不会提高吞吐量。将来的版本可能会利用CompletableFuture.delayedExecutor
来安排下一个过期事件,而无需直接创建线程(对于具有根据删除提示而具有业务逻辑的用户而言)。
ConcurrentLinkedHashMap
和MapMaker
同时编写,CLHM与咖啡因的性能相似。我相信差异是由于设计人员偏爱和优化了哪些方案而影响了其他功能的实现方式。悬而未决的果实可以使番石榴具有类似的性能表现,但没有一个内部冠军可以推动这一发展(以咖啡因为首选替代品更是如此)。