脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Go1.17 新特性,凭什么提速 5~10%?

Go1.17 新特性,凭什么提速 5~10%?

2021-08-31 00:12脑子进煎鱼了陈煎鱼 Golang

在 Go1.17 发布后,我们惊喜的发现 Go 语言他又又又优化了,编译器改进后产生了约 5% 的性能提升,也没有什么破坏性修改,保证了向前兼容。

Go1.17 新特性,凭什么提速 5~10%?

大家好,我是煎鱼。

在 Go1.17 发布后,我们惊喜的发现 Go 语言他又又又优化了,编译器改进后产生了约 5% 的性能提升,也没有什么破坏性修改,保证了向前兼容。

Go1.17 新特性,凭什么提速 5~10%?

他做了些什么呢,好像没怎么看到有人提起。为此今天煎鱼带大家来解读两新提案:

  • 《Proposal: Register-based Go calling convention[1]》
  • 《Proposal: Create an undefined internal calling convention[2]》

本文会基于提案讲解和拆解,毕竟分享新知识肯定要从官方资料作为事实基准出发。

背景

在以往的 Go 版本中,Go 的调用约定简单且几乎跨平台通用,其原因在于选用了基于 Plan9 ABI 的堆栈调用约定,也就是函数的参数和返回值都是通过堆栈上来进行传递。

这里我们一共提到了 Plan9 和 ABI,这是两个很关键的理念:

  • Plan9:Go 语言所使用的汇编器,Rob Pike 是贝尔实验室的猛人。
  • ABI:Application Binary Interface(应用程序二进制接口),ABI 包含了应用程序在操作系统下运行时必须遵守的编程约定(例如:二进制接口)。

该方案的优缺点如下:

  • 优点:实现简单,简化了实现成本。
  • 缺点:性能方面付出了不少的代价。

按我理解,在 Go 语言初创时期,采取先简单实现,跑起来再说。也合理,性能倒不是一个 TOP1 需求。

Go1.17 优化

什么是调用惯例

在新版本的优化中,提到了调用惯例(calling convention)的概念,指的是调用方和被调用方对函数调用的共识约定。

这些共识包含:函数的参数、返回值、参数传递顺序、传递方式等。

双方都必须遵循这个约定时,程序的函数才能正常的运行起来。如果不遵循,那么该函数是没法运行起来的。

优化是什么

在 Go1.17 起,正式开始基于 Go 内部 ABI 规范(在 Go 函数之间使用),并且从原有的基于堆栈的函数参数和结果传递的方式改为基于寄存器的函数参数和结果传递。

在性能上,现在直接存储和计算都在寄存器上,和以前基于堆栈存储,再计算相比,现在这种模式势必是性能更优的。

本次修改涉及到的项非常多,该优化是持续的,原本预计是 Go1.16 实现,不过拖到了 Go1.17。

Go1.17 新特性,凭什么提速 5~10%?

目前实现了 amd64 和 arm64 架构的支持。还有不少的更多的支持会持续在 Go1.18 中完成,具体进度可见 issues #40724[3]。

性能如何

在 Go1.17 Release Notes[4] 中明确指出,用一组有代表性的 Go 包和程序的基准测试。

官方数据显示:

  • Go 程序的运行性能提高了约 5%。
  • Go 所编译出的二进制大小的减少约 2%。

在民间数据来看,在 twitter[5] 看到 @Achille 表示从 Go1.15.7 升级到 Go1.17 后显示。在一个大规模的数据处理系统上进行的 Go1.17 升级产生了惊人的效果,我们来看看他的真实数据。

CPU、Malloc 调用时间减少了约15%:

Go1.17 新特性,凭什么提速 5~10%?

图来自 @Achille

Go1.17 新特性,凭什么提速 5~10%?

图来自 @Achille

RSS 大小更接近于堆的大小:

Go1.17 新特性,凭什么提速 5~10%?

图来自 @Achille

内存方面从原本的 1.6GB 降至 1GB。

结合官方和民间数据来看,优化效果是明确且有效的。有兴趣的小伙伴也可以自己测一测。

不过需要注意,@Achille 的数据是包含 Go1.16 和 Go1.17 的优化的,没法直接对比,但可以参考。

总结

在 Go1.17 这一个新版本中,只需要简单的升一升 Go 版本,我们就能得到一定的性能优化,这是非常不错的。

不过这一改动,Go 的汇编又变了,怕不是市面上很多文章或书的部分内容又失效了。

从以往的基于堆栈的函数参数和结果传递的方式改为 Go1.17~Go1.18 基于寄存器的函数参数和结果传递,Go 语言正在一步步走的更好!

你觉得呢?

参考资料

[1]Proposal: Register-based Go calling convention: https://go.googlesource.com/proposal/+/master/design/40724-register-calling.md

[2]Proposal: Create an undefined internal calling convention: https://go.googlesource.com/proposal/+/master/design/27539-internal-abi.md

[3]issues #40724: https://github.com/golang/go/issues/40724

[4]Go1.17 Release Notes: https://golang.org/doc/go1.17

[5]twitter: https://twitter.com/Achille/status/1431014148800802819

原文链接:https://mp.weixin.qq.com/s/cYnlPTM3R02_kZsIukmVfg

延伸 · 阅读

精彩推荐
  • GolangGolang通脉之数据类型详情

    Golang通脉之数据类型详情

    这篇文章主要介绍了Golang通脉之数据类型,在编程语言中标识符就是定义的具有某种意义的词,比如变量名、常量名、函数名等等,Go语言中标识符允许由...

    4272021-11-24
  • GolangGolang中Bit数组的实现方式

    Golang中Bit数组的实现方式

    这篇文章主要介绍了Golang中Bit数组的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    天易独尊11682021-06-09
  • Golanggolang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    李浩的life12792020-05-27
  • Golanggo日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    SmallQinYan12302021-02-02
  • Golanggo语言制作端口扫描器

    go语言制作端口扫描器

    本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下。 ...

    脚本之家3642020-04-25
  • Golanggolang的httpserver优雅重启方法详解

    golang的httpserver优雅重启方法详解

    这篇文章主要给大家介绍了关于golang的httpserver优雅重启的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    helight2992020-05-14
  • Golanggolang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看...

    Go语言中文网11352020-05-21
  • Golanggolang 通过ssh代理连接mysql的操作

    golang 通过ssh代理连接mysql的操作

    这篇文章主要介绍了golang 通过ssh代理连接mysql的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    a165861639710342021-03-08