Golang转义分析中'leak/leaking param'是什么意思

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=0和是什么意思leaking param: i1 to result \~r1 level=0


首先我尝试谷歌golang escape leaking,最相关的结果是在escape-analysis-shows-channel-as-leaking-param的评论中


“你为什么那么想?” 可以合理地假设泄漏是坏的并且与其阀杆泄漏有关。我正在努力想出一个泄漏是一件好事的示例上下文,例如泄漏桶、泄漏油箱、泄漏、泄漏电容器、泄漏船、泄漏抽象。对于高性能 go 专家来说这可能是显而易见的,但对于我们其他人来说,链接到文档并简要说明泄漏参数指的是什么会很有帮助


和我想问的是同一个问题,但是之后就没有回复了。


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


在compile/internal/escape/leaks.go中,我找到了评论


// 泄漏表示来自参数的一组赋值流


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


// 结果参数。


但我无法理解这一点,是否有任何官方文件来表示它。


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


Qyouu
浏览 207回答 1
1回答

叮当猫咪

参数 i1 泄漏到 ~r1 with derefs=0 和泄漏参数的含义是什么:i1 结果 ~r1 level=0TLDL:如果您正在寻找分配,请忽略泄漏的参数并寻找“移动到堆”的部分。“泄漏参数”意味着该函数在返回后以某种方式使其参数保持活动状态,这并不意味着它被移动到堆中,实际上大多数“泄漏参数”都分配在堆栈上。“r1”指的是函数的返回值,它从0开始,所以“r1”指的是第二个返回值。(与 OP 提供的示例代码不匹配,应该是 r0),在第一个片段的情况下,它泄漏了“i1”,因为“r0 = i1”,所以第 0 个函数返回值是“i1”,因此是“i1” " 返回后必须保持活动状态,“泄漏”给调用者编译器输出中“泄漏参数”之前的部分是因为 OP 使用“-m -m”,它打印数据流图。对于 deref,来自 cmd/compile/internal/escape/escape.go 中的注释:[...] 取消引用操作的数量减去寻址操作的数量被记录为边缘的权重(称为“derefs”)。“级别”在当前评论中没有描述,自从我熟悉 gc 源代码以来已经有一段时间了,据我所知,它是内存间接级别,间接 (*) 操作增量,地址 (&)递减,因此这个函数func A1(a **int) *int {    p := &a    return **p}应该给出一个 level=1 的泄漏参数a。此外,在源代码中我发现了一个问题。如果 numEscResults(7) 之后的结果参数会在运行时逃逸到堆中?是的,第 7 个之后取决于泄漏参数的所有结果(读取、返回)都将移至堆,我不知道 7 的确切原因,但我可以从 gc 源代码的经验中猜测它是一个值不会减慢太多编译速度,但会保留对大多数函数的优化
打开App,查看更多内容
随时随地看视频慕课网APP