Slide 1

Slide 1 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 1/26 Go Escape Analysis 2017/8/29 Koya Fukushi Eureka, Inc. Developer

Slide 2

Slide 2 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 2/26 エスケープ解析とは? サブルーチンにおいて変数やオブジェクトが割り当てられるとき、変数へのポインタ が、別の実行スレッドや呼び出し元のルーチンに「エスケープ」してしまうことがあ る。 オブジェクトがサブルーチン内で割り当てられ、オブジェクトへのポインタがエスケー プしなければ、そのオブジェクトはヒープの代わりにスタックに割り当てる候補にな る。 https://ja.wikipedia.org/wiki/ エスケープ解析 (https://ja.wikipedia.org/wiki/%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E8%A7%A3%E6%9E%90)

Slide 3

Slide 3 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 3/26 やってみる package main type S struct{} func main() { var x S _ = identity(x) } func identity(x S) S { return x }

Slide 4

Slide 4 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 4/26 やってみる -m エスケープ解析を出力 -l 関数のインライン化を無効(今回は例をわかりやすくするために) $ go run -gcflags '-m -l' escape_analysis.go $ 最初の例は何も出力されない(エスケープが無い)

Slide 5

Slide 5 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 5/26 やってみる package main type S struct{} func main() { var x S y := &x _ = *identity(y) } func identity(z *S) *S { return z }

Slide 6

Slide 6 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 6/26 やってみる $ go run -gcflags '-m -l' escape_analysis1.go # command-line-arguments ./escape_analysis1.go:11: leaking param: z to result ~r1 level=0 ./escape_analysis1.go:7: main &x does not escape go は関数の引数は値渡しなので、identity にz のコピーが渡される けどz はidentity で参照されていないのでエスケープされなかった

Slide 7

Slide 7 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 7/26 やってみる package main type S struct{} func main() { var x S _ = *ref(x) } func ref(z S) *S { return &z }

Slide 8

Slide 8 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 8/26 やってみる $ go run -gcflags '-m -l' escape_analysis2.go # command-line-arguments ./escape_analysis2.go:11: &z escapes to heap ./escape_analysis2.go:10: moved to heap: z ref はz の参照を返すから、z はref のスタックフレームに入らない main にも見えるようにヒープに格納される

Slide 9

Slide 9 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 9/26 やってみる package main type S struct { M *int } func main() { var i int refStruct(i) } func refStruct(y int) (z S) { z.M = &y return z }

Slide 10

Slide 10 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 10/26 やってみる $ go run -gcflags '-m -l' escape_analysis3.go # command-line-arguments ./escape_analysis3.go:13: &y escapes to heap ./escape_analysis3.go:12: moved to heap: y 構造体のフィールドであってもエスケープされる

Slide 11

Slide 11 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 11/26 やってみる package main type S struct { M *int } func main() { var i int refStruct(&i) } func refStruct(y *int) (z S) { z.M = y return z }

Slide 12

Slide 12 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 12/26 やってみる $ go run -gcflags '-m -l' escape_analysis4.go # command-line-arguments ./escape_analysis4.go:12: leaking param: y to result z level=0 ./escape_analysis4.go:9: main &i does not escape main のスタックフレーム内の参照だから、refStruct のz.y の値は知っている 参照が循環される。エスケープされない

Slide 13

Slide 13 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 13/26 やってみる package main type S struct { M *int } func main() { var x S var i int ref(&i, &x) } func ref(y *int, z *S) { z.M = y }

Slide 14

Slide 14 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 14/26 やってみる $ go run -gcflags '-m -l' escape_analysis5.go # command-line-arguments ./escape_analysis5.go:13: leaking param: y ./escape_analysis5.go:13: ref z does not escape ./escape_analysis5.go:10: &i escapes to heap ./escape_analysis5.go:9: moved to heap: i ./escape_analysis5.go:10: main &x does not escape 入力された構造体に代入している 解析での入力は出力の値に対してのみ許可されている

Slide 15

Slide 15 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 15/26 やってみる package main type S struct { M *int } func main() { ref() } func ref() (z S) { var i = [5]int{1, 2, 3, 4, 5} z.M = &i[0] return z }

Slide 16

Slide 16 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 16/26 やってみる $ go run -gcflags '-m -l' escape_analysis6.go # command-line-arguments ./escape_analysis6.go:13: &i[0] escapes to heap ./escape_analysis6.go:12: moved to heap: i 配列は一つの要素でもエスケープされてしまうと、全体もエスケープされる 一つもエスケープされないと、スタックフレームに乗る

Slide 17

Slide 17 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 17/26 やってみる package main type S struct { M *int } func main() { ref() } func ref() (z S) { var i = [5]int{1, 2, 3, 4, 5} _i := i[0] z.M = &_i return z }

Slide 18

Slide 18 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 18/26 やってみる $ go run -gcflags '-m -l' escape_analysis7.go # command-line-arguments ./escape_analysis7.go:14: &_i escapes to heap ./escape_analysis7.go:13: moved to heap: _i _i だけエスケープされた。 slice 全体じゃないので効率的

Slide 19

Slide 19 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 19/26 やってみる package main type S struct{} func main() { v := S{} m := make(map[int]*S) m[0] = &v }

Slide 20

Slide 20 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 20/26 やってみる $ go test -gcflags="-m -l" -bench=. escape_analysis8.go # command-line-arguments ./escape_analysis8.go:9: &v escapes to heap ./escape_analysis8.go:6: moved to heap: v ./escape_analysis8.go:8: main make(map[int]*S) does not escape map のvalue にセットされたポインターは常にエスケープされる

Slide 21

Slide 21 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 21/26 やってみる package main type S struct{} func main() { v := S{} m := []*S{} m[0] = &v }

Slide 22

Slide 22 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 22/26 やってみる $ go test -gcflags="-m -l" -bench=. escape_analysis8.go # command-line-arguments ./escape_analysis9.go:9: &v escapes to heap ./escape_analysis9.go:6: moved to heap: v ./escape_analysis9.go:8: main []*S literal does not escape slice のvalue にセットされたポインターは常にエスケープされる

Slide 23

Slide 23 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 23/26 まとめ stack を有効に使うことで高速化が可能 -gc ags="-m" をつけることでエスケープ解析を出力できる map とslice には要注意

Slide 24

Slide 24 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 24/26 Links Golang Escape Analisis blog.rocana.com/golang-escape-analysis (http://blog.rocana.com/golang-escape-analysis) Go Escape Analysis Flaws docs.google.com/document/d/1CxgUBPlx9iJzkz9JWkb6tIpTe5q32QDmz8l0BouG0Cw/preview (https://docs.google.com/document/d/1CxgUBPlx9iJzkz9JWkb6tIpTe5q32QDmz8l0BouG0Cw/preview)

Slide 25

Slide 25 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 25/26 Thank you Koya Fukushi Eureka, Inc. Developer https://github.com/Kooooya/ (https://github.com/Kooooya/)

Slide 26

Slide 26 text

2017/8/30 Go Escape Analysis http://go-talks.appspot.com/github.com/Kooooya/slides/2017/0829_with_navitime/escape_analysis_0.slide#1 26/26