我尝试对Go的Cache包进行了基准测试的经历

这篇帖子是Go4 Advent Calendar 2019第15天的内容。

晚上好!天气渐渐变冷了呢。

嗯,我们平时经常使用GCP。过一段时间会产生大量未被使用的资源,这给成本带来了压力。

在成本控制和库存工作中,我们想要找到没有进行生命周期设置或因各种原因很难设置,且未使用的磁盘。虽然aws cli有一个命令可以找到这些磁盘,但goolgle-cloud-sdk的gcloud命令没有。因此,我们决定自己创建这个命令。

https://github.com/k-oguma/gce-available-disks

在那个时候,作为一个选项,我们设定了在Stackdriver日志中搜索活动日志,以便能够确定是谁创建了该活动日志(保存期限很短)。

然而,在GCP项目中产生大量活动日志的场景下,搜索速度较慢。
另外也有讨论,可以首先投入到Bigquery中,类似AWS Athena的方式可能更好,但并不是所有项目都是如此,并且为了通用性且开源,我们选择使用本地缓存的方法。

因为这样的原因,我想使用 Go 的缓存,所以决定进行一些缓存包的性能测试。
这是我第一次使用 Go 的缓存包。
在这里,所谓的缓存是指本地缓存。

另外,在这次验证中,我们将保持原始设置而不进行任何调整。

验证环境

    • macOS Mojave v10.14.6

 

    • iMac 27 inch Retina 5K 27-inch, 2017

 

    • CPU 3.5GHz Intel Core i5

 

    • Memory 24GB DDR4

 

    Fusion drive 1TB

尝试过的包裹

我已经尝试了以下三种选项。

    • akyoto/cache

 

    • patrickmn/go-cache

 

    eko/gocache

在这些选项中,eko/gocache 是一个特殊的Go缓存库,其概念是使其能够与各种缓存机制进行集成。这与”go build”的环境变量GOCACHE无关。

eko/gocache的补充说明

在上述的三种选择中,eko/gocache 是通过采用现有元素进行开发的风格。

    • Built-in stores

Memory (bigcache) (allegro/bigcache)
Memory (ristretto) (dgraph-io/ristretto)
Memcache (bradfitz/memcache)
Redis (go-redis/redis)
More to come soon

我希望在这些选项中使用 bigcache 和 ristretto 进行本地缓存和验证。

注意事项的主题是gocache

在这里面,有一个最显著的特点。

    • import する際は、pathに注意してください

github.com/eko/gocache ではなく、 github.com/eko/gocache/cache などになります。

waitを入れないと実行で出来ません

time.Sleep(10 * time.Millisecond)

关于Bigcache

Bigcache是一个能够高速处理GB级别缓存大小的缓存系统。为了提高性能,Bigcache使用了一些技巧来避免使用sync.RWMutex等会阻塞写入的并发处理方式,并通过使用分片来合理分散并避免协程阻塞。选择使用分片的原因是当分片数量较多,且哈希函数能够将唯一键均匀分布时,竞争锁的冲突几乎可以最小化到零。此外,Bigcache还通过FIFO和时间戳比较的方式轻松地清除过时缓存,避免了对缓存条目执行垃圾回收操作,从而降低了延迟。详细内容请参考以下链接:
https://awesomeopensource.com/project/allegro/bigcache
https://allegro.tech/2016/03/writing-fast-cache-service-in-go.html
https://github.com/allegro/bigcache

意译:将以下内容以中文本地语言进行意译,只需提供一种选项:

当我们开始开发时,Go 1.6还处于RC阶段。我们最初采取的措施是将代码更新至最新的RC版本,以缩短请求处理时间。然而,在我们的情况下,性能几乎相同。于是我们开始寻找更高效的解决方案,并找到了fasthttp。这是一个提供零分配的HTTP服务器库。根据文档,综合测试显示它的速度是标准HTTP处理程序的10倍。尽管在我们的测试中,它只有1.5倍的提速,但仍然表现卓越!

关于所提到的 fasthttp,据公司验证,它已经经过验证,并且大大减少了内存分配,速度也得到了提升,验证结果展现出良好的性能。

关于Ristretto

对于Ristretto,似乎具有以下特点。

重点放在性能和准确性上的开发需求,使用Dgraph(一个可水平扩展的开源图数据库,支持类似GraphQL的查询语言,并支持Protocol Buffers通过GRPC和HTTP进行通信)开发了一个无竞争的缓存。
https://github.com/dgraph-io/benchmarks/tree/master/cachebench/ristretto
https://blog.dgraph.io/post/introducing-ristretto-high-perf-go-cache/

image.png

那么实际结果如何呢?我决定试一试这些方法。

我创建了一个用于测试的仓库。

我创建了类似于https://github.com/k-oguma/go-cache-benchmarks的东西。

测量规则和流程如下所示。

    1. 最初先执行内存flush操作。

由于不是共享内存,所以只需在首次执行即可。

在以下每个软件包的默认设置下进行相同内容的基准测试:

akyoto/cache
patrickmn/go-cache

在eko/gocache中的以下两个:

Bigcache
Ristretto

执行一字符的Cache Set和Get操作,以及Delete操作的测量。

执行长文本内容的Cache Set和Get操作,以及Delete操作的测量。

我们将根据上述的测量内容进行实际测量。

请确保这些都能进行Set和Get操作。
由于gocache有些特殊,请参考已注释的内容。

用法

帮助

make help

进行基准测试

make test

结果

% make test
Benchmark target:  /Users/katsuyuki/go/src/github.com/k-oguma/go-cache-benchmarks/cache
goos: darwin
goarch: amd64
pkg: github.com/k-oguma/go-cache-benchmarks/cache
BenchmarkAppend_CacheEveryTime-4                          560948              1919 ns/op             744 B/op         15 allocs/op
BenchmarkAppend_CacheForLargeStringsEveryTime-4           634150              2236 ns/op             744 B/op         15 allocs/op
PASS
ok      github.com/k-oguma/go-cache-benchmarks/cache    2.546s
----------------------
Benchmark target:  /Users/katsuyuki/go/src/github.com/k-oguma/go-cache-benchmarks/go-cache
goos: darwin
goarch: amd64
pkg: github.com/k-oguma/go-cache-benchmarks/go-cache
BenchmarkAppend_CacheEveryTime-4                          379837              3836 ns/op             909 B/op         11 allocs/op
BenchmarkAppend_CacheForLargeStringsEveryTime-4           222919              4854 ns/op             913 B/op         11 allocs/op
PASS
ok      github.com/k-oguma/go-cache-benchmarks/go-cache 2.717s
----------------------
Benchmark target:  /Users/katsuyuki/go/src/github.com/k-oguma/go-cache-benchmarks/gocache
goos: darwin
goarch: amd64
pkg: github.com/k-oguma/go-cache-benchmarks/gocache
BenchmarkAppend_CacheEveryTimeForBigcache-4                           62          39577989 ns/op        337197180 B/op     11301 allocs/op
BenchmarkAppend_CacheForLargeStringsEveryTimeForBigcache-4            36          37570676 ns/op        337200235 B/op     11302 allocs/op
BenchmarkAppend_CacheEveryTimeForRistretto-4                          74          15981556 ns/op        50624497 B/op        548 allocs/op
BenchmarkAppend_CacheForLargeStringsEveryTimeForRistretto-4           76          15482215 ns/op        50625023 B/op        548 allocs/op
PASS
ok      github.com/k-oguma/go-cache-benchmarks/gocache  6.365s
----------------------
スクリーンショット 2019-12-16 0.27.10.png
スクリーンショット 2019-12-16 0.37.24.png

结果出乎意料。这次是使用默认设置进行的,并未进行任何调整,因此结果可能会有所变化。此外,gocache有一些特性,但同时也内置了各种缓存包,因此可以像链式缓存那样进行缓存的连结,似乎朝着更高功能的方向发展。

在https://github.com/k-oguma/gce-available-disks上,我已决定使用go-cache。

如果你知道其他类似的Go缓存实现方式或者有推荐的Go缓存包,麻烦告诉我一声,我会非常感激。

另外,我也想要亲自研究一下并尝试自己去制作。

明天将是mergit先生的文章!

广告
将在 10 秒后关闭
bannerAds