0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

马哥Linux运维 来源:量子位 作者:量子位 2022-11-24 15:48 次阅读

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

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

e60973ee-6b35-11ed-8abf-dac502259ad0.png

简直就像是……

e61cb9cc-6b35-11ed-8abf-dac502259ad0.png

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

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

不过顺着这个思路发现有人发现,就连Go开发团队的核心人物Russ Cox都在标准库中犯过同样的错误。

e62da426-6b35-11ed-8abf-dac502259ad0.png

什么样的错误?

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

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

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

e6596aac-6b35-11ed-8abf-dac502259ad0.png

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

e66c4546-6b35-11ed-8abf-dac502259ad0.png

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

e6894498-6b35-11ed-8abf-dac502259ad0.png

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

另外在内存动态分配malloc和垃圾回收gc上面的花费也值得注意。

e69a928e-6b35-11ed-8abf-dac502259ad0.png

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

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

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

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

e6ad0fcc-6b35-11ed-8abf-dac502259ad0.png

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

再分析一下代码,发现在给rule赋值的时候实际上是做了一次不必要的拷贝,后面用“&”取地址时候创建了一个逃逸的指针指向它的副本。

e6c1220a-6b35-11ed-8abf-dac502259ad0.png

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

e6d2be98-6b35-11ed-8abf-dac502259ad0.png

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

如何彻底避免?

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

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

e6f17946-6b35-11ed-8abf-dac502259ad0.png

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

e705e700-6b35-11ed-8abf-dac502259ad0.png

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

e719c388-6b35-11ed-8abf-dac502259ad0.png

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

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

审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 代码
    +关注

    关注

    30

    文章

    4556

    浏览量

    66775
  • go语言
    +关注

    关注

    1

    文章

    157

    浏览量

    8927

原文标题:只改变一个字符使 Go 程序提速 42%

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何提取串口接收字符串数组里的某个字符串?

    条(有时候二十多条不定)响应字符串指令,我是用一个字符串数组来接收这些返回来的指令的。我现在只需要读取数组里的某条指令,应该怎么把它提取出来啊??有哪位前辈懂的,希望能提供点帮助。我找了好久找到
    发表于 04-22 06:05

    深入解析西门子博途文本块接口的结构与功能

    STRING 和 WSTRING 数据类型存储一个字符串中的多个字符。允许在字符串中使用任何 ASCII码类型的字符。这些字符将使用一个单引
    发表于 04-11 11:23 99次阅读
    深入解析西门子博途文本块接口的结构与功能

    使用i2c从从站读取两个字节时,为什么主站发送一个字节后就发送NACK呢?

    当我使用 i2c 从从站读取两个字节时,有时会返回 RX_OVERFLOW。 我使用逻辑分析仪抓取总线波形,发现接收到一个字节,主控器发出 NACK,之后返回错误代码
    发表于 03-05 07:42

    oracle判断字符串包含某个字符

    字符串操作是任何编程语言中都非常重要的一部分,Oracle数据库作为目前最常用的关系型数据库之一,也提供了丰富的字符串操作函数和方法。在本文中,我们将详细解析如何在Oracle中判断一个字符串是否
    的头像 发表于 12-06 09:53 5467次阅读

    mysql字符串包含某个字符

    MySQL是一种开源的关系型数据库管理系统,被广泛用于构建Web应用程序和其他大型数据驱动的应用。在进行MySQL数据库查询时,经常需要使用字符串包含操作,即判断一个字符串是否包含另一个字符
    的头像 发表于 11-16 14:52 1149次阅读

    如何使用JDK截断一个字符

    目标。 使用JDK截断一个字符串 Java提供了许多方便的方法来截断一个 String 。让我们来看看。 使用 String 的 substring() 方法 String 类有一个方便的方法,叫做
    的头像 发表于 10-08 15:43 316次阅读

    代码字符串分割方法

    我们写代码的时候,经常会遇到这样一个场景,那就是分割字符串。比如说把一个字符串分成N个,或者说按照N个字符分割。 我们今天就来看看怎么每隔N个字符分割
    的头像 发表于 09-25 11:42 426次阅读

    谈谈一个字符的网路旅程

    我们开发的面向普通用户的应用程序,目前看来几乎都是互联网应用程序,也就是说,用户操作的应用程序,不管是浏览器还是移动App,核心请求都会通过互联网发送到后端的数据中心进行处理。
    的头像 发表于 07-31 09:57 410次阅读
    谈谈<b class='flag-5'>一个字符</b>的网路旅程

    KUKA机器人系统函数StrCopy()复制字符串变量的方法

    用函数 StrCopy() 可以将字符串变量的内容复制到另一个字符串变量中。
    的头像 发表于 07-21 10:04 762次阅读

    KUKA机器人: 如何比较两个字符串变量

    用功能 StrComp() 可以比较两个字符串变量。 Comp = StrComp( StrComp1[], StrComp2[], CaseSens )
    的头像 发表于 07-10 09:27 629次阅读

    Python字符与字节

    一个字符不等价于一个字节,字符是人类能够识别的符号,而这些符号要保存到计算的存储中就需要用计算机能够识别的字节来表示。一个字符往往有多种表示方法,不同的表示方法会使用不同的字节数。这里
    的头像 发表于 07-05 15:55 670次阅读

    如何遍历中文字符

    今天和大家分享下如何遍历中文字符串,主要是如何打印中文字符,因为中文字符串每个字符占用不只一个字节的空间,如果我们逐
    的头像 发表于 07-03 09:15 391次阅读
    如何遍历中文<b class='flag-5'>字符</b>串

    STRING的使用方法

    数据类型为 STRING 的操作数在一个字符串中存储多个字符,最多可包括 254 个字符。在一个字符串中,可使用系统所创建代码页的所有字符
    的头像 发表于 06-18 10:34 705次阅读
    STRING的使用方法

    西门子博途:STRING的使用

    数据类型为 STRING 的操作数在一个字符串中存储多个字符,最多可包括 254 个字符。在一个字符串中,可使用系统所创建代码页的所有字符
    的头像 发表于 06-16 15:51 1.4w次阅读
    西门子博途:STRING的使用

    Python中检查字符串包含的方法

    Python 有多种处理字符串的方法。今天我们介绍如何检查一个字符串中是否包含另一个字符串。
    的头像 发表于 05-14 16:02 1.4w次阅读