簡體   English   中英

HashMap vs ConcurrentHashMap vs LoadingCache(番石榴)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM