您现在的位置是:首页 > 作品 >

作品

Go程序提速42%,只需改变一个字符

2025-02-07 10:06:27作品56
Go程序提速42%,只需改变一个字符 梦晨 发自 凹非寺量子位 | QbitAIGo语言本来就以轻量快速著称,一位GitHub员工却偶然发现:只改变一个字符的位置,能把一段代码运行速度提高足足42%。简直就像是……这个简单有效的技巧一经发布,就引来众多程序员围观。原作者自己也调侃,一般这种情况都是事先犯了个愚蠢的错误,后面才能提升这么大。不过顺着这个思路发现有人发现,就连Go开发团队

Go程序提速42%,只需改变一个字符

梦晨 发自 凹非寺

量子位 | QbitAI

Go语言本来就以轻量快速著称,一位GitHub员工却偶然发现:

只改变一个字符的位置,能把一段代码运行速度提高足足

42%

简直就像是……

这个简单有效的技巧一经发布,就引来众多程序员围观。

原作者自己也调侃,一般这种情况都是事先犯了个愚蠢的错误,后面才能提升这么大。

不过顺着这个思路发现有人发现,就连

Go开发团队的核心人物Russ Cox都在标准库中犯过同样的错误

什么样的错误?

发现这个问题的Harry在大型程序员交友平台GitHub工作。

他在开发一个把GitHub仓库中每个文件的所有者列出来的小工具。

功能很简单,就是根据CODEOWERS文件中定义的规则匹配,写在越下面的规则优先级越高。

原理也很简单,就是从后往前一条一条处理,匹配到了就停止。

但就是这样一个简单的程序却出现了性能问题,处理中等大小的仓库就很慢了。

他打印出火焰,发现大部分时间都花在了Go语言的正则表达式引擎中。

另外在

内存动态分配malloc

垃圾回收

gc

上面的花费也值得注意。

要减少malloc的时间,就需要用到Go语言的逃逸分析(Escape Analysis)了。

简单来说,就是尽量把变量分配到栈上,让编译器自动管理内存的释放。

只有在“逃逸”也就是变量的作用域超出所在的栈时,才把变量分配到堆上,减轻运行时GC的压力。

在这次的程序中,Harry确定了逃逸的变量是rule这个结构体(struct)。

但问题是,rule存储在RuleSet这个切片(slice)里,按Go语言的规则可以确信他已经在堆中了。

再分析一下代码,发现在给rule赋值的时候实际上是做了一次不

必要的拷贝

,后面用“&”取地址时候创建了一个逃逸的指针指向它的副本。

最后解决办法也很容易想出,只需要把&移动到上面。

这样就引用了切片中的结构体,避免了拷贝。

如何彻底避免?

在热议中,有网友分享了自己是怎么避免出现这个问题的。

对于每个结构体,把它看作纯值或纯指针,压根就不去使用&这种取地址的操作,避免隐式的内存分配。

如果你想要深入理解这个问题,也有人贴心的给出了需要提前了解的一些背景知识。

最后有人指出,Rust语言为避免这个问题,直接规定必须显式操作才能拷贝一个数据结构。

当你不习惯的时候这规定烦得要命,但是总的来看还是值得。

方便or规范,你更倾向于哪种做法?

参考链接:

[1]https:///blog/goallocationhunting/

[2]https://news./item?id=

— 完 —

量子位 QbitAI · 头条号签约

留言与评论(共有 16 条评论)
本站网友 尿毒症是怎么引起的
9分钟前 发表
减轻运行时GC的压力
本站网友 双流租房
21分钟前 发表
发现大部分时间都花在了Go语言的正则表达式引擎中
本站网友 传奇3红人网
19分钟前 发表
只需要把&移动到上面
本站网友 睿智是什么意思
23分钟前 发表
当你不习惯的时候这规定烦得要命
本站网友 口腔工艺
16分钟前 发表
原理也很简单
本站网友 天津购房政策
1分钟前 发表
就需要用到Go语言的逃逸分析(Escape Analysis)了
本站网友 未定
6分钟前 发表
但是总的来看还是值得
本站网友 广发华福大智慧
7分钟前 发表
不过顺着这个思路发现有人发现
本站网友 杨志刚吧
2分钟前 发表
减轻运行时GC的压力
本站网友 梦见自己溺水
12分钟前 发表
方便or规范
本站网友 五通桥租房
12分钟前 发表
让编译器自动管理内存的释放
本站网友 武昌租房网
16分钟前 发表
发现在给rule赋值的时候实际上是做了一次不必要的拷贝
本站网友 凤凰平台网址
28分钟前 发表
简直就像是……这个简单有效的技巧一经发布
本站网友 中锗科技
2分钟前 发表
减轻运行时GC的压力
本站网友 电驴资源搜索
24分钟前 发表
后面用“&”取地址时候创建了一个逃逸的指针指向它的副本