「每日一庫」一個零 GC 的緩存庫:freecache

商業世界裡,現金為王;架構世界裡,緩存為王。


「每日一庫」一個零 GC 的緩存庫:freecache

今天給大家推薦一個零 GC 開銷、高併發性能的緩存庫:FreeCache,項目地址:https://github.com/coocood/freecache,Star 數:2.5k+。

我們知道內存中的對象長期存在會帶來昂貴的 GC 開銷,使用 FreeCache,你## 特性

  • 能存儲數億個條目
  • 零 GC 開銷
  • 高併發線程安全訪問
  • 純 Go 實現
  • 過期支持
  • 類似 LRU 算法
  • 嚴格限制內存使用
  • 附帶一個小服務器,支持帶有管道功能的基本 Redis 命令
  • 迭代器支持

性能

這是基準測試結果與內置 map 的比較結果;Set 性能比內置 map 快約 2 倍;Get 性能比內置 map 慢約 1/2 倍。由於它是基於單線程做的基準測試,因此在多線程環境中,FreeCache 應該比單鎖保護的內置 map 快許多倍。

<code>BenchmarkCacheSet        3000000               446 ns/op
BenchmarkMapSet 2000000 861 ns/op
BenchmarkCacheGet 3000000 517 ns/op
BenchmarkMapGet 10000000 212 ns/op/<code>

使用示例

<code>cacheSize := 100 * 1024 * 1024
cache := freecache.NewCache(cacheSize)
debug.SetGCPercent(20)
key := []byte("abc")
val := []byte("def")
expire := 60 // expire in 60 seconds
cache.Set(key, val, expire)
got, err := cache.Get(key)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(string(got))
}
affected := cache.Del(key)
fmt.Println("deleted key ", affected)
fmt.Println("entry count ", cache.EntryCount())/<code>

它怎麼做到零 GC 開銷的?

FreeCache 通過減少指針數量避免了 GC 開銷。無論其中存儲了多少條目,都只有 512 個指針。通過 key 的哈希值將數據集分割為 256 個段。每個段只有兩個指針,一個是存儲鍵和值的環形緩衝區,另一個是用於查找條目的索引切片。每個段都有自己的鎖,因此它支持高併發訪問。


分享到:


相關文章: