go 逃逸分析 翻译

翻译自
https://www.ardanlabs.com/blog/2018/01/escape-analysis-flaws.html

https://docs.google.com/document/d/1CxgUBPlx9iJzkz9JWkb6tIpTe5q32QDmz8l0BouG0Cw/edit#heading=h.tvvbikdq3so3

1 间接赋值

1)创建main,go,内容如下


package main

type X struct {
    p *int
}

func main() {

    for i := 0; i < 10; i++ {

        var i1 int

        x1 := &X{

            p: &i1,
        }

        _ = x1

        var i2 int

        x2 := &X{}

        x2.p = &i2

    }

}
  1. go build -gcflags '-m' main.go, 显示

./main.go:17:10: &i2 escapes to heap

./main.go:15:7: moved to heap: i2

./main.go:11:7: main &i1 does not escape

./main.go:11:4: main &X literal does not escape

./main.go:16:9: main &X literal does not escape

2 间接调用

1) 创建main,go,内容如下

package main

func main() {

    for i := 0; i < 10; i++ {

        var y1 int

        foo(&y1, 42)

        var y2 int

        func(p *int, x int) {

            *p = x

        }(&y2, 42)

        var y3 int

        p := foo

        p(&y3, 42)

    }

}

func foo(p *int, x int) {

    *p = x

}

2) go build -gcflags '-m' main.go, 显示


./main.go:19:6: can inline foo

./main.go:6:6: inlining call to foo

./main.go:9:3: can inline main.func1

./main.go:11:4: inlining call to main.func1

./main.go:19:10: foo p does not escape

./main.go:15:5: &y3 escapes to heap

./main.go:13:7: moved to heap: y3

./main.go:6:7: main &y1 does not escape

./main.go:11:5: main &y2 does not escape

3 slice和map 赋值

1) 创建main,go,内容如下

package main

func main() {

    for i := 0; i < 10; i++ {

        m := make(map[int]*int)

        var x1 int

        m[0] = &x1 // BAD: cause of x1 escape

        s := make([]*int, 1)

        var x2 int

        s[0] = &x2 // BAD: cause of x2 escape

    }

}

2) go build -gcflags '-m' main.go, 显示


./main.go:7:10: &x1 escapes to heap

./main.go:6:7: moved to heap: x1

./main.go:11:10: &x2 escapes to heap

./main.go:10:7: moved to heap: x2

./main.go:5:12: main make(map[int]*int) does not escape

./main.go:9:12: main make([]*int, 1) does not escape

4 interface

1) 创建main,go,内容如下


package main

type Iface interface {
    Method()
}

type X struct {
    name string
}

func (x X) Method() {}

func main() {

    for i := 0; i < 10; i++ {

        x1 := X{"bill"}

        var i1 Iface = x1

        var i2 Iface = &x1

        i1.Method() // BAD: cause copy of x1 to escape

        i2.Method() // BAD: cause x1 to escape

        x2 := X{"bill"}

        foo(x2)

        foo(&x2)

    }

}

func foo(i Iface) {

    i.Method() // BAD: cause value passed in to escape

}

2) go build -gcflags '-m' main.go, 显示


./main.go:11:6: can inline X.Method

./main.go:11:7: X.Method x does not escape

./main.go:28:10: leaking param: i

./main.go:16:7: x1 escapes to heap

./main.go:17:7: &x1 escapes to heap

./main.go:17:18: &x1 escapes to heap

./main.go:15:3: moved to heap: x1

./main.go:23:6: x2 escapes to heap

./main.go:24:7: &x2 escapes to heap

./main.go:24:7: &x2 escapes to heap

./main.go:22:3: moved to heap: x2

:1: leaking param: .this

:1: (*X).Method .this does not escape

5 未知

1) 创建main,go,内容如下

package main

import "bytes"

func main() {

    for i := 0; i < 10; i++ {

        var buf bytes.Buffer

        buf.Write([]byte{1})

        _ = buf.Bytes()

    }

}

2) go build -gcflags '-m' main.go, 显示


./main.go:9:16: inlining call to bytes.(*Buffer).Bytes

./main.go:8:6: buf escapes to heap

./main.go:7:7: moved to heap: buf

./main.go:8:19: main []byte literal does not escape

./main.go:9:10: main buf does not escape

你可能感兴趣的:(go 逃逸分析 翻译)