为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
Qyouu 2022-11-23 20:40:55
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=0parameter 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)会在运行时逃逸到堆中?
查看完整描述

1 回答

?
叮当猫咪

TA贡献1776条经验 获得超12个赞

参数 i1 泄漏到 ~r1 with derefs=0 和泄漏参数的含义是什么:i1 结果 ~r1 level=0

TLDL:如果您正在寻找分配,请忽略泄漏的参数并寻找“移动到堆”的部分。

“泄漏参数”意味着该函数在返回后以某种方式使其参数保持活动状态,这并不意味着它被移动到堆中,实际上大多数“泄漏参数”都分配在堆栈上。

“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 源代码的经验中猜测它是一个值不会减慢太多编译速度,但会保留对大多数函数的优化


查看完整回答
反对 回复 2022-11-23
  • 1 回答
  • 0 关注
  • 179 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信