快速,并发,驱逐记忆缓存,以保留大量条目而不会影响性能。 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许可下发布(请参阅许可证)