'leak/leaking param'在Golang逃逸分析中的含义是什么


func main() {
i1 := 1
A1(&i1)
}
func A1(i1 *int) *int {
return i1
}

逃逸分析的结果是

./main.go:18:9: parameter i1 leaks to ~r1 with derefs=0:
./main.go:18:9:   flow: ~r1 = i1:
./main.go:18:9:     from return i1 (return) at ./main.go:19:2
./main.go:18:9: leaking param: i1 to result ~r1 level=0

parameter i1 leaks to ~r1 with derefs=0leaking param: i1 to result ~r1 level=0的含义是什么


首先我尝试谷歌golang escape leaking,最相关的结果是在逃逸分析的评论中显示通道为泄漏参数

"你为什么会这么想"可以合理地假设泄漏是严重的,并且与阀杆泄漏有关。我很难想出一个漏水是好事的例子,比如水桶漏水、油箱漏水、漏水、电容器漏水、船漏水、抽象物漏水。对于高性能go专家来说,这可能是显而易见的,但对于我们其他人来说,链接到文档并简要说明泄漏参数指的是将是很有帮助的

这是我想问的同一个问题,但之后没有更多回复。


然后我尝试读取打印这些结果的源代码。

在compile/internal/escape/leaks.go中,我发现了评论

//泄漏表示来自参数的一组分配流

//到堆或其任何函数的(第一个numEscResults(

//结果参数。

但我不明白,有什么官方文件可以代表它吗?


此外,在源代码中,我发现了另一个问题。numEscResults(7)之后的结果参数是否会在运行时转义到堆?

func main() {
i1, i2, i3, i4, i5, i6, i7, i8, i9 := 1, 1, 1, 1, 1, 1, 1, 1, 1
A1(&i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8, &i9)
return
}
func A1(i1, i2, i3, i4, i5, i6, i7, i8, i9 *int) (*int, *int, *int, *int, *int, *int, *int, *int, *int) {
return i1, i2, i3, i4, i5, i6, i7, i8, i9
}
...some duplicate output
./main.go:16:13: leaking param: i2 to result ~r10 level=0
./main.go:16:17: leaking param: i3 to result ~r11 level=0
./main.go:16:21: leaking param: i4 to result ~r12 level=0
./main.go:16:25: leaking param: i5 to result ~r13 level=0
./main.go:16:29: leaking param: i6 to result ~r14 level=0
./main.go:16:33: leaking param: i7 to result ~r15 level=0
./main.go:16:37: leaking param: i8
./main.go:16:41: leaking param: i9
./main.go:8:30: i8 escapes to heap:
./main.go:8:30:   flow: {heap} = &i8:
./main.go:8:30:     from &i8 (address-of) at ./main.go:9:40
./main.go:8:30:     from A1(&i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8, &i9) (call parameter) at ./main.go:9:4
./main.go:8:34: i9 escapes to heap:
./main.go:8:34:   flow: {heap} = &i9:
./main.go:8:34:     from &i9 (address-of) at ./main.go:9:45
./main.go:8:34:     from A1(&i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8, &i9) (call parameter) at ./main.go:9:4
./main.go:8:30: moved to heap: i8
./main.go:8:34: moved to heap: i9

参数i1泄漏到~r1的含义是什么,derefs=0,泄漏参数i1以导致~r1级别=0

TLDL:如果您正在查找分配,请忽略泄漏的参数并查找";移动到堆";碎片。

A";泄漏参数";意味着这个函数在返回后以某种方式保持其参数的有效性,这并不意味着它被移动到堆中,事实上;泄漏参数";在堆栈上分配。

"r1";是指函数的返回值,它从0开始,所以"r1";参考第二返回值。(它与OP提供的示例代码不匹配,应该是r0(,在第一个片段泄漏的情况下;i1";因为";r0=i1";,所以第0个函数返回值是"0";i1";因此";i1";必须在返回后保持生命,";"泄漏";到主叫

在";泄漏参数";在编译器输出中是因为OP使用了"-m-m",它打印数据流图。

对于deref,来自cmd/compile/internal/escape/eescape.go:中的注释

[…]解引用操作的数量减去寻址操作被记录为边缘的权重(称为"derefs"(。

"电平";在当前的注释中没有描述,而且我已经有一段时间没有熟悉gc源代码了,据我所知,这是内存间接级别,一个间接(*(操作增量,地址(&(递减,因此这个函数

func A1(a **int) *int {
p := &a
return **p
}

应给出级别为1的泄漏参数CCD_ 5。

此外,在源代码中,我发现了另一个问题。numEscResults(7(之后的结果参数是否会在运行时转义到堆?

是的,第7个之后的所有结果(读取,返回(都将被移到堆中,这取决于泄漏的参数,我不知道7的确切原因,但我可以根据gc源代码的经验猜测,这个值不会太慢编译,但保留了大多数函数的优化

最新更新