[英]HashMap vs ConcurrentHashMap vs LoadingCache(Guava)
要在 spring 引导应用程序中本地缓存一些数据,哪种技术在读/写操作方面会更好? HashMap vs ConcurrentHashMap vs LoadingCache(Guava library) 我分别尝试了写和读操作,HashMap最快,LoadingCache最慢,那我们为什么要使用LoadingCache呢?
编辑:应用程序是多线程的。 缓存的最大大小、到期时间等功能可能会受到影响。 此外,主要动机是提高读取速度。
如果您的应用程序是多线程的并且缓存由线程共享,那么HashMap
不是一个选项。 它不是线程安全的,如果你用锁等保护它,锁定很容易成为并发瓶颈。
如果你的应用程序需要缓存是 LRU 或者有一些其他的“智能”策略来决定驱逐什么,那么ConcurrentHashMap
并没有提供一个很好的方法来做到这一点。 如果您希望您的缓存对 memory 压力敏感(例如使用弱引用键),那么ConcurrentHashMap
也不会这样做。
这就是 Guava Cache
类的用武之地。阅读本文以了解它们提供的功能。
底线是,虽然HashMap
在单线程基准测试中性能最高,但它可能无法提供您需要的所有功能。 性能不是一切。
我的建议是先让代码正常工作……然后再考虑优化它的方法。 偶尔中断或填满 memory 的超快速缓存实现不是一个好主意。 而且很有可能缓存读/写性能无论如何都不重要。
关于性能,它取决于数据的大小和读取之间的修改比率。 这是一个建议:
Static 数据:如果您的数据是 static,请在构造函数中初始化只读 map,如下所示:
final Map map;
MyClass(Map inputMap) {
map = Map.copyOf(inputMap);
}
Object get(Object key) {
return map.get(key);
}
罕见的修改:如果你有很少的修改并且数据不是太大:
volatile Map map = Map.of();
Object synchronized put(Object key, Object value) {
Map mutable = new HashMap(map);
mutable.put(key, value);
map = Map.copyOf(mutable);
}
Object get(Object key) {
return map.get(key);
}
The Map.copyOf
is available since Java 9. It creates an immutable hash table, that is using an open addressing scheme, unlike HashMap
. 这将比HashMap
更快。 您还可以在多线程环境中将HashMap
与上述方案一起使用,因为它一旦创建就不会被修改。
需要synchronized
,以确保在多个线程同时使用put
时不使用更新。 需要volatile
以确保更新在其他线程中可见。
主要动机是提高读取速度。
因此,上述解决方案将提供最佳读取速度,但会影响更新速度。
大量数据和/或大量修改:使用ConcurrentHashMap
。
即使有轻微的性能优势,我还是建议使用ConcurrentHashMap
,因为:
ConcurrentHashMap
被证明可以工作。 你会用多线程编写单元测试来证明你的代码可以正常工作吗?脚注:
缓存的使用
Cache 和LoadingCache
: Guava LoadingCache
旨在与CacheLoader
一起使用。 缓存加载器可用于使缓存自动填充缓存和/或进行刷新。 与此同时,Guava 缓存已经过时,我建议在寻找在 Java 堆中工作的缓存解决方案时查看 Caffin 或cache2k 。
缓存在读取路径中总是有额外的开销,因为它需要做一些簿记才能知道当前访问了哪些条目。 至少根据我的(免责声明...)基准测试,cache2k 的开销是最小的。
Spring 开机
当与 Spring 缓存抽象一起使用时,例如使用@Cacheable
,在实现中不会有很大的性能差异,因为缓存抽象也有非常相关的开销。
Spring 中基于ConcurrentHashMap
的简单cache
实现仅用于测试和原型设计。 我建议始终尽快使用真正的缓存实现并设置合理的资源限制。
分析和优化整个应用程序
您所做的每项优化都有权衡,因此您应该始终查看整个应用程序并将“优化”与可能的最简单或最常见的解决方案进行比较。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.