点击上方蓝色“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 的效果如下:
小弟我就问了一句 这个 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 性能的结果放了出来
无闻大佬用这个命令测试了一番,发现差距特别大,结果差了 20 倍之多。最后得知无闻大佬用的命令如下,原来是加了 race 竞态检测。
$go test -v -cover -race -test.bench=. -test.benchmem
最后发现加上 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 的文章:
- Race 源码[6]
- Go 译文之竞态检测器 race[7][官方 blog]
- Data Race Detector[8][官方 blog]
- Golang race detection[9]
- Data races in Go(Golang) and how to fix them[10]
- go run -race 的底层实现[11]
推荐阅读
GCTT 出品 | 在 Go 中发现竞态条件 (Race Conditions)
Go 为什么能成功?Rob Pike 认为做了这 5 件事
喜欢本文的朋友,欢迎关注“Go语言中文网”:
文中链接 [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