前言
早在幾年前寫過關於 LRU cache
的文章:
https://crossoverjie.top/2018/04/07/algorithm/LRU-cache/
當時是用 Java 實現的,最近我在完善 ptg 時正好需要一個最近最少使用的資料結構來儲存歷史記錄。
ptg: Performance testing tool (Go), 用 Go 實現的 gRPC 客戶端除錯工具。
Go 官方庫中並沒有相關的實現,考慮到程式的簡潔就不打算依賴第三方庫,自己寫一個;本身複雜度也不高,沒有幾行程式碼。
配合這個資料結構,我便在 ptg 中實現了請求歷史記錄的功能:
將每次的請求記錄儲存到 lru cache 中,最近使用到的歷史記錄排在靠前,同時也能提供相關的搜尋功能;具體可見下圖。
實現
實現原理沒什麼好說的,和 Java
的一樣:
- 一個雙向連結串列儲存資料的順序
- 一個
map
儲存最終的資料 - 當資料達到上限時移除連結串列尾部資料
- 將使用到的
Node
移動到連結串列的頭結點
雖然 Go 比較簡潔,但好訊息是基本的雙向連結串列結構還是具備的。
所以基於此便定義了一個 LruCache
:
根據之前的分析:
size
儲存快取大小。- 連結串列儲存資料順序。
map
儲存資料。lock
用於控制併發安全。
接下來重點是兩個函式:寫入、查詢。
寫入時判斷是否達到容量上限,達到後刪除尾部資料;否則就想資料寫入頭部。
而獲取資料時,這會將查詢到的結點移動到頭結點。
這些結點操作都由 List 封裝好了的。
所以使用起來也比較方便。
最終就是通過這個 LruCache
實現了上圖的效果,想要了解更多細節的可以參考原始碼: