Go 从版本 1.0 到 1.22的性能变化

程序员咋不秃头2024-04-18 19:50:56  60

两年前,我在 1.2 到 1.18 的所有 Go 版本上比较了 GoAWK 解释器的两个不同基准。

在本文中,我重新运行这些基准测试,添加缺少的 Go 版本(1.0 和 1.1)以及新版本(1.19 到 1.22)。我还包含了 Go 1.20 中添加的配置文件引导优化 (PGO) 的结果。我将引用我原来文章中的一些内容,这样您就不必重新阅读旧文章来理解设置。

用 Go 编写的程序可以通过多种方式变得更快:Go 团队和外部贡献者改进了编译器,并优化了运行时、垃圾收集器和标准库。在这里,我们比较了使用 Go 的每个发布版本(从 1.0 到 1.22)(撰写本文时的最新版本)编译时 GoAWK 的性能。

我通过在两个 AWK 程序上运行 GoAWK 来测试这一点,这两个程序代表了使用 AWK 可以执行的不同极端操作:带有字符串处理的 I/O 和数字运算。

首先,我们有 countwords ,一个字符串处理任务,它计算输入中单词的频率并打印出单词及其计数。这是 AWK 脚本的典型情况。输入是 King James Bible 的 10 倍串联版本(我之前用过它来进行性能比较)。代码如下:

{ for (i=1; i<=NF; i++) counts[tolower($i)]++}END { for (k in counts) print k, counts[k]}

第二个程序是 sumloop ,一个紧密循环,它将循环计数器多次添加到变量中。这实际上并不是 AWK 的典型用法,但可以很好地测试 GoAWK 字节码解释器循环:

BEGIN { for (i=0; i<10000000; i++) sum += i+i+i+i+i}

我必须稍微调整 GoAWK 的代码才能使其在较旧的 Go 版本上进行编译。特别是对于 Go 1.0,因为它没有 bufio.Scanner ,而 GoAWK 大量使用它。我在 1.0 中使用了 bufio.Scanner 的 Go 1.1 实现。

图表中的计时数字是我的 x86-64 Linux 笔记本电脑上的时间(以秒为单位)(三轮运行中最好的)。蓝线是 countwords ,红线是 sumloop (顺便说一句,我上次错误地标记了结果)。请注意,这次 Y 轴是对数的,以便更清楚地看到最近版本中更微妙的改进。

图表中还包括每个 Go 版本的 GoAWK 二进制大小 - 即浅灰色线。

我再次使用 Python 脚本来运行它们并测量时间。这是图表(如果您愿意,也可以作为表格):

最大的改进来自版本 1.3、1.5、1.7 和 1.12。之后,速度会逐渐加快——所有容易实现的目标都早已被采摘了。

这次,Go 1.2 中的 countwords 出现了奇怪的变化:它从 1.1 中的 7.5 秒增加到 1.2 中的 25.5 秒(!),然后在 1.3 中下降到 2.8 秒。这几乎肯定是由堆栈“热分割”问题引起的,该问题在 1.3 中得到了修复,因为 Go 团队将“goroutine 堆栈的实现从旧的‘分段’模型更改为连续模型”。

我通过分析找出了 1.2 异常的原因,并注意到运行时堆栈操作占了运行时间的很大一部分。这是 pprof 输出的前几行:

$ go tool pprof --text ./goawk_1.2 go12.prof Total: 1830 samples 332 18.1% 18.1% 332 18.1% runtime.newstack 296 16.2% 34.3% 296 16.2% runtime.memclr 281 15.4% 49.7% 281 15.4% runtime.oldstack 222 12.1% 61.8% 619 33.8% github.com/benhoyt/goawk/interp.(*interp).execute 91 5.0% 66.8% 91 5.0% runtime.lessstack 75 4.1% 70.9% 133 7.3% github.com/benhoyt/goawk/interp.(*interp).callBuiltin 57 3.1% 74.0% 57 3.1% runtime.stackfree 53 2.9% 76.9% 81 4.4% strings.FieldsFunc ...

使用 Go 1.22,PGO 仅提高了几个百分点的性能, countwords 大约提高了 2%, sumloop 提高了 7%。我使用 PGO 编译发布的 GoAWK 二进制文件。

除了 1.2 中的大幅增长之外,多年来二进制大小一直保持相当稳定。即使启用了 PGO,二进制文件也只会大 5% 左右,所以我认为这通常是值得的。

总体而言, countwords 现在的速度大约是 Go 1.0 的 8 倍, sumloop 的速度是 Go 1.0 的 24 倍。感谢Go团队多年来的辛勤付出!

转载此文是出于传递更多信息目的。若来源标注错误或侵犯了您的合法权益,请与本站联系,我们将及时更正、删除、谢谢。
https://www.414w.com/read/389359.html
0
随机主题
出道似整容! 天庭饱满地阁方圆的金晨, 原来12年前和现在判若两人迪拜土豪14米长巨型豪车,奥尼尔看了都摇头!G1东欧爆种, 不然想晋级都难? 森林狼绅士横扫独行侠不在话下泽连斯基将前往法国说服北约击落俄罗斯导弹, 没收俄国被冻结资产今年荔枝让人“高攀不起”? 整体减产, 妃子笑已经降价大雾黄色预警: 黄海东北部等将有能见度不足1公里的大雾库尔勒森林消防大队大力开展实战化野外化练兵活动手机弹出“系统更新”提示, 大多数人会这样做! 看看老师傅怎么说吞噬星空大改, 界中界血腥混战, 罗峰抱大腿, 雾大人杀疯了英雄年代手游: 勇气与智慧的结合, 十年之约经典回归!老头杯最强三费诞生! 无脑四保一害惨Uzi, lwx被最菜下路线杀三次楚悦辰: 5.23黄金现价2380空单进场, 目标2350外卖小哥看泰山比赛落泪, 王大雷: 我想以最真诚的方式表示感谢A股忽然全线下跌,真正原因明眼人都懂?逆向思维,把握逢低时机实测电脑内存条DDR5的 7600能比6400频率提升多少帧 内存条避坑指南赵云:常山龙胆,三国风云中的不朽传奇俄罗斯从三家欧洲银行扣押了价值超过7亿欧元的资产返佣高达14%, 银行争抢这一消费场景欧文: 我时刻提醒队友失败是什么感觉 登顶夺冠又是什么感觉申花客胜河南《DOTA2》游戏迎来 7.36 重磅更新: 首次推出先天技能、英雄命石
最新回复(0)