go cmd/compile: combine append calls

c2e8gylq  于 3个月前  发布在  Go
关注(0)|答案(6)|浏览(23)

当前,编译器不会将 A 重写为 B,并为 A(或更一般地说,对于同一切片的 N 个连续追加操作)生成 2 个 append 序列。合成基准测试显示了这两种形式之间的相当大差异。
Go 源代码中有多个地方可以使用这种重写:
大多数它们都不是性能关键的。
我已经对实际代码进行了一些影响测量:
请注意,为了看到差异,需要修改 AppendQuoteRune,因为否则它不会执行带有追加操作的路径:
我看到的主要问题是潜在的影响,例如行信息和调试体验(一个追加序列而不是预期的 N)。我还认为切片表达式应该是“安全”的。参数也可能需要这个属性来避免在求值可能导致行信息更改的情况下发生 panic。
一旦获得批准,我希望深入研究这个问题并提供优化实现。我已经发送了 CL117615 - net: combine append calls in reverseaddr,因为这似乎在那里是有好处的。如果这个优化永远不会在编译器内部实现,我们无论如何都会得到那个提升。

sc4hvdpw

sc4hvdpw1#

如果我们能找到一个合理的调试信息的样子,那就很好了。

2g32fytz

2g32fytz2#

这也可能是一个很好的提示,用于性能导向的类似工具。cc @dominikh

acruukt9

acruukt93#

我希望这不会引发某种工具战争。:)

yyhrrdl8

yyhrrdl84#

这个例子展示了一些可观察到的行为差异:
https://play.golang.org/p/LTV703gJTYR
这让我觉得这种优化对编译器来说是不有效的。
为了方便,我把代码复制到这里:

package main

import (
	"fmt"
)

func before() {
	xs := make([]int, 1, 1)
	xs[0] = 6
	ys := xs[:0]
	ys = append(ys, 1)
	ys = append(ys, 2)
	fmt.Println(xs, ys) // [1] [1 2]
}

func after() {
	xs := make([]int, 1, 1)
	xs[0] = 6
	ys := xs[:0]
	ys = append(ys, 1,2)	
	fmt.Println(xs, ys) // [6] [1 2]
}

func main() {
	before()
	after()
}
oxf4rvwz

oxf4rvwz5#

Example provided by @TocarIP

3npbholx

3npbholx6#

Punting to unplanned, too late for anything major in 1.12.

相关问题