9.6 编译日志
与内联一样,我们可以通过编译参数 -m
来反馈编译器的逃逸分析结果。将下列代码保存到文件 main.go
中:
package main
type T struct {
Name string
}
func escapeAnalysis(arg T) (*T, bool) {
l1 := arg
l1.Name = "Golang"
l2 := &l1
l3 := *l2
return &l3, arg.Name == "Java"
}
通过命令 go tool compile -G=3 -m -json "0,file:///tmp/main.json" main.go
进行编译,可以看到如下输出:
main.go:7:21: leaking param: arg main.go:12:2: moved to heap: l3
可见只有变量 l3 逃逸到了堆上,与上文中我们分析的一致。
文件 /tmp/main.json
也会包含相关信息。其中 -m
对应的数字越大,日志就越详细,例如我们通过命令 go tool compile -G=3 -m=2 -json "0,file:///tmp/main.json" main.go
编译时,得到的结果如下:
main.go:12:2: l3 escapes to heap: main.go:12:2: flow: ~r1 = &l3: main.go:12:2: from &l3 (address-of) at main.go:13:9 main.go:12:2: from return &l3, arg.Name == string(“Java”) (return) at main.go:13:2 main.go:7:21: parameter arg leaks to l3 with derefs=0: main.go:7:21: flow: l1 = arg: main.go:7:21: from l1 := arg (assign) at main.go:8:5 main.go:7:21: flow: l2 = &l1: main.go:7:21: from &l1 (address-of) at main.go:11:8 main.go:7:21: from l2 := &l1 (assign) at main.go:11:5 main.go:7:21: flow: l3 = *l2: main.go:7:21: from *l2 (indirection) at main.go:12:8 main.go:7:21: from l3 := *l2 (assign) at main.go:12:5 main.go:7:21: leaking param: arg main.go:12:2: moved to heap: l3
其中 -m -m
与 -m=2
效果一样,当 -m=4
时,日志还会打印出内联前后的 IR Tree 结构,读者可以自己尝试。
最后更新于
这有帮助吗?