go string 转 uint64_小改动,大提升:最近 Go 标准库的一次优化
点击上方蓝色“Go语言中文网”关注我们,领全套Go资料,每天学习 Go 语言
本文作者:鸟窝 smallnest,原文有视频讲解
原文链接:https://colobu.com/2019/12/31/small-changes-big-improvement/
Carlo Alberto Ferraris 提交了一个对math/rand
库中的lockedSource
优化的 pr(CL#191538[1]),核心代码其实只有一行,却带来了相对的巨大的性能提升,让我们一起老看看这次的修改,学习一下代码的优化技巧,提高我们 Go 语言的底层优化经验。
实际测试中第三个保持在同一个cacheline
优化并没有起作用,反而采用指针类型性能更好一点点。我实际测试发现也发现这个优化也没有特别明显的优化效果,所以下面的测试中并没有这个优化手段。
下面我们通过一个例子 ? 来比较采用这个方法前后的代码的性能,主要观察接口去掉后的性能提升和内联后的性能提升。
首先定义一个干果DryFruit
的接口,它有一些通用的方法,比如名称、价格以及增加数量的方法(Increase), 因为只是做个演示,你不必深究这些方法的意义:
// DryFruit 干果接口.type DryFruit interface { Name() string Price() uint64 Family() string Distribution() string Increase()}
下面我们定义一个栗子 ? 对象,它实现了干果接口:
// Chestnut 栗子.type Chestnut struct { name string count uint64}
// Name 名称.func (c Chestnut) Name() string {return c.name}
// Price 价格.func (c Chestnut) Price() uint64 {return 10}
// Family Family name.func (c Chestnut) Family() string {return "Fagaceae"}
// Distribution 分布.func (c Chestnut) Distribution() string {return "East Asia"}
// Increase 数量加一func (c *Chestnut) Increase() { c.count++}
接口和具体的实现都定义好了,我们需要定义一个使用它们的对象:礼物Gift
。
未优化的礼物定义如下, 定义了一个OriginGift
对象,它包含一个排外锁,还包含一个干果接口字段:
// OriginGift 未优化之前的礼物对象.type OriginGift struct { mu sync.Mutex dryFruit DryFruit}
// Access 访问接口对象.func (g *OriginGift) Access() { g.dryFruit.Name() g.dryFruit.Price() g.dryFruit.Family() g.dryFruit.Distribution() g.dryFruit.Increase()}
而我们的优化的 Gift struct 直接把接口对象替换成具体的栗子 struct:
// ImprovedGift 优化后的礼物对象.type ImprovedGift struct { mu sync.Mutex dryFruit *Chestnut}
// Access 访问具体的字段对象.func (g *ImprovedGift) Access() { g.dryFruit.Name() g.dryFruit.Price() g.dryFruit.Family() g.dryFruit.Distribution() g.dryFruit.Increase()}
Benchmark 测试代码如下:
func BenchmarkOriginGift(b *testing.B) {var nut = &OriginGift{ dryFruit: &Chestnut{name: "栗子"}, }for i := 0; i < b.N; i++ { nut.Access() }}
func BenchmarkImprovedGift(b *testing.B) {var nut = &ImprovedGift{ dryFruit: &Chestnut{name: "栗子"}, }for i := 0; i < b.N; i++ { nut.Access() }}
func BenchmarkOriginGiftParallel(b *testing.B) {var nut = &OriginGift{ dryFruit: &Chestnut{name: "栗子"}, } b.RunParallel(func(pb *testing.PB) {for pb.Next() { nut.mu.Lock() nut.Access() nut.mu.Unlock() } })}
func BenchmarkImprovedGiftParallel(b *testing.B) {var nut = &ImprovedGift{ dryFruit: &Chestnut{name: "栗子"}, } b.RunParallel(func(pb *testing.PB) {for pb.Next() { nut.mu.Lock() nut.Access() nut.mu.Unlock() } })}
同时测试无并发的 benchmark, 然后测试并发访问时的性能。
第一次测试我们采用禁止内联的方式, 运行go test -gcflags "-N -l" -bench .
:
goos: darwingoarch: amd64pkg: github.com/smallnest/study/perf_interfaceBenchmarkOriginGift-4 34669898 31.0 ns/opBenchmarkImprovedGift-4 58661895 17.9 ns/opBenchmarkOriginGiftParallel-4 7292043 171 ns/opBenchmarkImprovedGiftParallel-4 8718816 143 ns/op
可以看到将接口替换成具体的 struct 优化还是很明显的,非并发访问的情况下耗时几乎降到了一半,并发访问也有可观的性能提升。
第二次我们启用内联,看看和上面不启用内联的情况比较。
goarch: amd64pkg: github.com/smallnest/study/perf_interfaceBenchmarkOriginGift-4 95278143 12.6 ns/opBenchmarkImprovedGift-4 549471100 2.16 ns/opBenchmarkOriginGiftParallel-4 11631438 115 ns/opBenchmarkImprovedGiftParallel-4 13815229 86.3 ns/op
启用内联后,可以看到性能都有所提升,而去掉接口的方式性能优化更明显,直接降到了2.16 ns/op
。
通过这两个 benchmark 的比较,你应该能深刻理解到这两种优化手段(去接口、内联)带来的巨大收益吧。
你可以通过
go test --gcflags "-m -m" -bench .
了解内联的具体细节。
参考资料
[1]
CL#191538: https://go-review.googlesource.com/c/go/+/191538/
推荐阅读
xxx
喜欢本文的朋友,欢迎关注“Go语言中文网”:
Go语言中文网启用微信学习交流群,欢迎加微信:274768166
go string 转 uint64_小改动,大提升:最近 Go 标准库的一次优化相关推荐
- 谈谈两种标准库类型---string和vector
两种最重要的标准库---string和vector string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列. 一.标准库 ...
- 从零开始学C++之标准库类型(一):string 类简介和例程
一.标准库string类型 string类型支持长度可变的字符串,C++标准库将负责管理与存储字符相关的内存,以及提供各种有用的操作 ,在VC中直接F1查看 template <class Ch ...
- java怎么让多个方法循环运行下去_35 个小细节,提升 Java 代码的运行效率!你知道几个?...
原标题:35 个小细节,提升 Java 代码的运行效率!你知道几个? 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个 ...
- 走进科学-小菌株大作为—枯草芽孢杆菌替代畜牧业抗生素添加
我国是世界上最大的抗生素生产和使用国,同时也是细菌耐药性的重灾区.抗生素滥用问题在医疗特别是畜牧业领域尤其严重.畜牧业养殖户普遍将饲用抗生素添加到饲料中,当做保健品给动物防病,促进动物生长.而这会导致 ...
- 央视与遗传发育所合拍《走进科学-小菌株大作为》——枯草芽孢杆菌替代畜牧业抗生素添加
我国是世界上最大的抗生素生产和使用国,同时也是细菌耐药性的重灾区.抗生素滥用问题在医疗特别是畜牧业领域尤其严重.畜牧业养殖户普遍将饲用抗生素添加到饲料中,当做保健品给动物防病,促进动物生长.而这会导致 ...
- 小块头大性能才能得到用户的青睐
小块头大性能才能得到用户的青睐<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" ...
- 高密自智,体小量大,希捷Exos Corvault存储系统为数据洞察赋能
2022年2月24日--全球领先的海量数据存储基础设施解决方案提供商希捷科技(NASDAQ:STX)在线上举办了主题为"高密自智,体小量大"的新一代PB级自修复存储系统--Exos ...
- 中台彻底搞砸了?下一站,小中台大前台
作者| Mr.K 责编| 丁恩华 上周,老 K 受邀参加了一场大型线下技术峰会,作了中台方面的主题演讲,现场反馈热烈,微信加到爆.演讲的内容,总结了 2020 年中台在行业的实践,以及老 K 对中 ...
- 拨号盘拨号数字间距太小 调大 修改通讯录里面收藏和所有联系人字体颜色
Z:\80_l_hct_third\update\tengtai\v138f_qhd_tengtai_t36_b1b5_4Gb\packages\apps\PhoneCommon\res\values ...
最新文章
- JS设计模式(13)状态模式
- 蚂蚁金服面试3+2次,最终有惊无险通过!
- Xshell高级后门完整分析报告
- r 保留之前曲线_R简单数据处理和分析
- Common tasks for MySQL
- assert函数_PHP 之 assert()函数
- 【离散数学】浅析小项与主析取范式和大项与主合取范式
- 信息学奥赛一本通 1092:求出e的值 | OpenJudge NOI 1.5 35
- 作用于HTML元素的Vue.js指令
- 基于情感词典的情感值分析
- 「leetcode」617. 合并二叉树:【三种递归】【一种迭代】详解
- pp助手苹果版_PP助手将下架?越狱时代已经过去,到底是该喜该悲
- 放大镜css图标,CSS放大镜的制作
- [英语语法]句法之句子成分和种类
- 星际迷航中企业号的动力系统_五月四日与您同在:《星球大战》(和《星际迷航》)如何激发现实生活中的技术...
- C#学习笔记:GDI图形高级编程(1)——如何将图形画到控件上
- 第十二周项目四----利用遍历思想求解图问题之7最远顶点
- 【CodeForces300D】Painting Square
- 老有“美女”加你微信?大学生“艳遇”,结果吓一跳...
- Kotlin使用高阶函数实现多方法回调
热门文章
- C库函数-perror()
- 怎么html跟asp结合,xml与asp简单结合实现html模板功能.doc
- envoy实现_微服务之服务治理:Envoy 全局 gRPC 限速服务 lyft/ratelimit 详解
- matlab 傅里叶变换_Matlab与傅里叶变换
- TransDecoder
- 农林废弃物如何变废为宝?
- CHM:植物利用细菌获得真菌抗性!中山大学李剑峰课题组揭示植物免疫预警新机制...
- 不需要懂得编程,但却可以使用ggplot2画出论文级别的图?
- R语言可视化散点图(scatter plot)、并在散点图中叠加回归曲线、叠加lowess拟合曲线(linear and lowess fit lines)、使用plot、line、abline函数
- pandas使用groupby函数按照多个分组变量进行分组聚合统计、使用agg函数计算分组的多个统计指标(grouping by multiple columns in dataframe)