#This article takes a look at how much benefits changes in function calling conventions can bring to Go.
InGo Function Calling Conventions In the article (it is recommended that readers who are not familiar with this section read this article first), we discussed the function calling conventions of the Go language.
The so-called function calling convention refers to a certain agreement that the function caller and the callee must abide by, mainly including the method of passing in and out parameters of the function, the order of passing them, etc.
Parameter passing methods are generally divided into two situations: register passing and stack passing.
Before Go 1.17, the Go language used stack transfer to avoid differences between different CPU registers. The biggest advantage of this approach is that it is simple to implement and makes the compiler easy to maintain. But the disadvantages are also obvious: some performance will be sacrificed. Because the speed of CPU access registers will be much higher than that of memory.
基于性能考虑,寄存器的调用惯例,是大多数语言采纳的方式。Go 也准备做点改变,在 1.17 版本中,对于 linux/amd64, darwin/amd64, windows/amd64 系统,首先实现了新的基于寄存器的调用惯例。
1 2 3 4 5 6 7 8 9 10 |
|
我们在 darwin/amd64 系统上,分别使用 Go 1.17 和 Go 1.16 的代码进行编译,得到它们的汇编语句分别如下。
Go 1.17 汇编语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
Go 1.16 汇编语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
看到这么多汇编代码,不要紧张。这里我们需要留意的就以下这么几行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
看出差异了吗?
在 Go 1.17 的汇编代码中,参数值 100 和 200 直接基于寄存器 AX 和 BX 来操作。而 Go 1.16 中,参数值是通过指向栈顶的栈指针寄存器SP的偏移量来表示和传递的。
在 Go 1.17 的release notes中,编译器的此项改变会让 Go 程序运行性能和二进制大小两个方面得到优化,
首先,我们比较编译后的二进制大小。
1 2 3 4 5 |
|
可以看出,Go 1.17 基于寄存器传递的函数调用惯例编译出的二进制,相较于 Go 1.16 基于栈传递的减少 4.8% 的大小。
通过 benchmark 比较程序执行效率
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
从 1.469 ns/op 提升至 1.257 ns/op,大约提升了 14%。
我们常谈论到,Go 是在不断优化迭代的,我们值得期待与建设更好的 Go 语言。
In order to reduce the performance loss based on stack transfer, starting from Go 1.17, compilation changes based on register transfer are introduced, which currently only supports the amd64 platform. But in Go 1.18, support for arm64, ppc64, and ppc64le platforms will be expanded.
As mentioned in Go's release notes, the new function calling convention will bring improvements in two aspects: the compiled binary size will be smaller and execution efficiency will be improved. At the same time, to maintain compatibility with existing assembly functions, the compiler generates adapter functions that convert between the old and new calling conventions.
The above is the detailed content of How much faster can Go's new function calling convention be?. For more information, please follow other related articles on the PHP Chinese website!