快速,並發,驅逐記憶緩存,以保留大量條目而不會影響性能。 BigCache將條目留在堆上,但為他們省略了GC。為了實現這一目標,進行字節切片進行操作,因此在大多數用例中需要在緩存前的條目(DE)序列化。
需要1.12或更新。
import (
"fmt"
"context"
"github.com/allegro/bigcache/v3"
)
cache , _ := bigcache . New ( context . Background (), bigcache . DefaultConfig ( 10 * time . Minute ))
cache . Set ( "my-unique-key" , [] byte ( "value" ))
entry , _ := cache . Get ( "my-unique-key" )
fmt . Println ( string ( entry ))當可以提前預測緩存負載時,最好使用自定義初始化,因為可以以這種方式避免其他內存分配。
import (
"log"
"github.com/allegro/bigcache/v3"
)
config := bigcache. Config {
// number of shards (must be a power of 2)
Shards : 1024 ,
// time after which entry can be evicted
LifeWindow : 10 * time . Minute ,
// Interval between removing expired entries (clean up).
// If set to <= 0 then no action is performed.
// Setting to < 1 second is counterproductive — bigcache has a one second resolution.
CleanWindow : 5 * time . Minute ,
// rps * lifeWindow, used only in initial memory allocation
MaxEntriesInWindow : 1000 * 10 * 60 ,
// max entry size in bytes, used only in initial memory allocation
MaxEntrySize : 500 ,
// prints information about additional memory allocation
Verbose : true ,
// cache will not allocate more memory than this limit, value in MB
// if value is reached then the oldest entries can be overridden for the new ones
// 0 value means no size limit
HardMaxCacheSize : 8192 ,
// callback fired when the oldest entry is removed because of its expiration time or no space left
// for the new entry, or because delete was called. A bitmask representing the reason will be returned.
// Default value is nil which means no callback and it prevents from unwrapping the oldest entry.
OnRemove : nil ,
// OnRemoveWithReason is a callback fired when the oldest entry is removed because of its expiration time or no space left
// for the new entry, or because delete was called. A constant representing the reason will be passed through.
// Default value is nil which means no callback and it prevents from unwrapping the oldest entry.
// Ignored if OnRemove is specified.
OnRemoveWithReason : nil ,
}
cache , initErr := bigcache . New ( context . Background (), config )
if initErr != nil {
log . Fatal ( initErr )
}
cache . Set ( "my-unique-key" , [] byte ( "value" ))
if entry , err := cache . Get ( "my-unique-key" ); err == nil {
fmt . Println ( string ( entry ))
}LifeWindow & CleanWindow LifeWindow是一個時代。在那段時間之後,一個條目可以被稱為死亡,但沒有被刪除。
CleanWindow是個時代。在那段時間之後,所有死者條目都將被刪除,而不是仍然擁有生命的條目。
比較了三個緩存:BigCache,Freecache和Map。使用I7-6700K CPU @ 4.00GHz進行基準測試,在Ubuntu 18.04 LTS上使用32GB RAM(5.2.12-050212代)進行。
基準源代碼可以在此處找到
go version
go version go1.13 linux/amd64
go test -bench=. -benchmem -benchtime=4s ./... -timeout 30m
goos: linux
goarch: amd64
pkg: github.com/allegro/bigcache/v3/caches_bench
BenchmarkMapSet-8 12999889 376 ns/op 199 B/op 3 allocs/op
BenchmarkConcurrentMapSet-8 4355726 1275 ns/op 337 B/op 8 allocs/op
BenchmarkFreeCacheSet-8 11068976 703 ns/op 328 B/op 2 allocs/op
BenchmarkBigCacheSet-8 10183717 478 ns/op 304 B/op 2 allocs/op
BenchmarkMapGet-8 16536015 324 ns/op 23 B/op 1 allocs/op
BenchmarkConcurrentMapGet-8 13165708 401 ns/op 24 B/op 2 allocs/op
BenchmarkFreeCacheGet-8 10137682 690 ns/op 136 B/op 2 allocs/op
BenchmarkBigCacheGet-8 11423854 450 ns/op 152 B/op 4 allocs/op
BenchmarkBigCacheSetParallel-8 34233472 148 ns/op 317 B/op 3 allocs/op
BenchmarkFreeCacheSetParallel-8 34222654 268 ns/op 350 B/op 3 allocs/op
BenchmarkConcurrentMapSetParallel-8 19635688 240 ns/op 200 B/op 6 allocs/op
BenchmarkBigCacheGetParallel-8 60547064 86.1 ns/op 152 B/op 4 allocs/op
BenchmarkFreeCacheGetParallel-8 50701280 147 ns/op 136 B/op 3 allocs/op
BenchmarkConcurrentMapGetParallel-8 27353288 175 ns/op 24 B/op 2 allocs/op
PASS
ok github.com/allegro/bigcache/v3/caches_bench 256.257sBigCache的寫入和讀物比Freecache快。寫映射是最慢的。
go version
go version go1.13 linux/amd64
go run caches_gc_overhead_comparison.go
Number of entries: 20000000
GC pause for bigcache: 1.506077ms
GC pause for freecache: 5.594416ms
GC pause for map: 9.347015ms go version
go version go1.13 linux/arm64
go run caches_gc_overhead_comparison.go
Number of entries: 20000000
GC pause for bigcache: 22.382827ms
GC pause for freecache: 41.264651ms
GC pause for map: 72.236853ms
測試表明,填充20毫升條目的緩存的GC停頓了多長時間。 BigCache和Freecache的GC暫停時間非常相似。
您可能會遇到系統內存報告似乎是指數增長的內容,但是這是預期的行為。進行運行時,將內存分配在塊或“跨度”中,並在將其更改為“閒置”時不再要求操作系統時通知操作系統。 “跨度”將保留在流程資源使用中的一部分,直到OS需要重新利用該地址為止。在此處提供進一步的閱讀。
BigCache依賴於1.5版GO(第9477頁)中提供的優化。該優化指出,如果使用鍵和值中沒有指針的映射,則GC將省略其內容。因此,BigCache使用map[uint64]uint32其中鍵在鍵上,值是條目的偏移。
條目保存在字節切片中,以再次省略GC。字節切片大小可以長到千兆字節而不會影響性能,因為GC只會看到單個指針。
BigCache無法處理碰撞。當插入新項目並與先前存儲的項目相撞時,新項目覆蓋先前存儲的值。
這兩個緩存都提供相同的核心功能,但它們以不同的方式減少了GC開銷。 BigCache依賴於map[uint64]uint32 ,Freecache實現了自己的映射,以減少指針數量。
基準測試的結果如上所述。 BigCache而不是FreeCache的優點之一是,您不需要提前知道緩存的大小,因為當BigCache已滿時,它可以為新條目分配其他內存,而不是像FreeCache當前那樣覆蓋現有的條目。但是,也可以設置BigCache中的Hard Max大小,請檢查HardMaxCachesize。
該軟件包還包括易於部署的HTTP實現BigCache,可以在服務器軟件包中找到。
BigCache Genesis在Allegro.Tech博客文章中描述:在GO中編寫非常快速的緩存服務
BigCache在Apache 2.0許可下發布(請參閱許可證)