go io.reader 读取string_两位Go大佬的对话引发的对 Race 的思考总结

点击上方蓝色“Go语言中文网”关注我们,领全套Go资料,每天学习 Go 语言

开始煎鱼大佬和无闻大佬在讨论 go-ini/ini[1] 这个库为什么不加个WatchConfig[2]的功能呢?另一个加载配置文件的库 viper[3] 有类似的功能。其实这是很常见的需求,不用修改代码, 修改一下配置文件即可实现热更配置。以下是大佬们的对话:


无闻大佬

  • 这得引入 fsnotify[4] 这个第三方库
  • 内置监控更新就等于要内部保证线程安全
  • 不过我先 mark 一下 viper,也许哪天洗脚就灵光一现!
  • 我现在自己用 ini 加载读取 i18n 字符串,因为每个页面渲染都有上百次读取调用,所以读性能是肯定要优先保证的
  • i18n 主要依赖这两个指标,粗暴理解就是 map[string]map[string]的读取。。我觉得是语言的极限了,除非改用别的数据结构 tire 之类的,但是还没试过,可能还不如现在的快...还要更多内存

煎鱼大佬

  • 快的话,放个评测呀,不然广大网友不好对比。

无闻大佬:

  • 跟谁做评测啊。。哈哈

煎鱼大佬:

  • 看来是天下无敌了(调侃)

于是无闻大佬抛出了自己的 benchmark 的结果。代码路径在 https://github.com/go-ini/ini/blob/d4cae42d398bc0095297fc3315669590d29166ea/bench_test.go ,主要看 Direct 方法的性能

benchmark 的效果如下:

9c2621df9a49757db5efaac4efdff535.png
image.png

小弟我就问了一句 这个 benchmark 的默认时间是 10s 吧 (原来是 1 秒,我之前还总结过,真是老了记忆越来越不好了),benchmark 的源码在 https://golang.org/src/testing/benchmark.go 。benchTime 的定义如下:

benchTime = benchTimeFlag{d: 1 * time.Second} // changed during test of testing package

于是小弟也看了下自己在在 go test 这块的总结,go test 中 -benchtime flag 的说明,默认确实是 1s。

-benchtime t
Run enough iterations of each benchmark to take t, specified as a time.Duration (for example, -benchtime 1h30s). The default is 1 second (1s).

讨论完这个后,我把之前压测 zap 的 Info 性能的结果放了出来

3d3710ad74ae48eb23dce6870c06650a.png
image.png

无闻大佬用这个命令测试了一番,发现差距特别大,结果差了 20 倍之多。最后得知无闻大佬用的命令如下,原来是加了 race 竞态检测。

$go test -v -cover -race -test.bench=. -test.benchmem
17f134226e98189e4f983423c1539e2c.png
image.png

最后发现加上 race 会使内存占用和执行时间增加好多倍,Go 官方 Blog 中 Golang race detection[5] 写到

The cost of race detection varies by program,
but for a typical program, memory usage may increase by 5-10x and execution time by 2-20x.

关于加上 race 为何会有如此多的性能消耗,找了一些资料了解到, race 检测的一些函数是由汇编实现的,当开启 -race 时 raceenabled 会为 true,从而会对一些竞态资源进行检测。官方 readme 中关于 race 的解释是

runtime/race package contains the data race detector runtime library.
It is based on ThreadSanitizer race detector, that is currently a part of
the LLVM project

最后推荐几篇关于 race 的文章:

  1. Race 源码[6]
  2. Go 译文之竞态检测器 race[7][官方 blog]
  3. Data Race Detector[8][官方 blog]
  4. Golang race detection[9]
  5. Data races in Go(Golang) and how to fix them[10]
  6. go run -race 的底层实现[11]

推荐阅读

GCTT 出品 | 在 Go 中发现竞态条件 (Race Conditions)

Go 为什么能成功?Rob Pike 认为做了这 5 件事

喜欢本文的朋友,欢迎关注“Go语言中文网”:

da80e6b0417ea91f1320bafd9cdb65ef.png

文中链接 [1]

go-ini/ini: https://github.com/go-ini/ini

[2]

WatchConfig: https://github.com/spf13/viper/blob/master/viper.go#L285:17

[3]

viper: https://github.com/spf13/viper

[4]

fsnotify: https://github.com/fsnotify/fsnotify

[5]

Golang race detection: https://krakensystems.co/blog/2019/golang-race-detection

[6]

Race源码: https://github.com/golang/go/tree/master/src/runtime/race

[7]

Go 译文之竞态检测器 race: https://segmentfault.com/a/1190000020107431

[8]

Data Race Detector: https://golang.org/doc/articles/race_detector.html

[9]

Golang race detection: https://krakensystems.co/blog/2019/golang-race-detection

[10]

Data races in Go(Golang) and how to fix them: https://www.sohamkamani.com/blog/2018/02/18/golang-data-race-and-how-to-fix-it/

[11]

go run -race的底层实现: https://speakerdeck.com/kavya719/go-run-race-under-the-hood

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值