LoginSignup
52
29

More than 5 years have passed since last update.

Goのコンパイル時の最適化結果を確認する(インライン化の条件についても記載)

Last updated at Posted at 2017-05-29

はじめに

下記のページの「Quick look at some compiler’s optimizations」の翻訳のようなものです。そもそも下記のページを見つけるのに結構苦労した&日本語情報があまりなかったのでメモ。

最適化の結果を確認する

  • go buildgo test の際に -gcflags=-m をつけると下記のように最適化結果が出力される
$ go build -gcflags=-m t.go
# command-line-arguments
./t.go:15: can inline NewUser
./t.go:21: inlining call to NewUser
./t.go:10: leaking param: u
./t.go:10: leaking param: u
./t.go:12: (*User).Greetings ... argument does not escape
./t.go:15: leaking param: name
./t.go:15: leaking param: location
./t.go:17: &User literal escapes to heap
./t.go:15: leaking param: name
./t.go:15: leaking param: location
./t.go:21: &User literal escapes to heap
./t.go:22: main ... argument does not escape

ちなみに t.go はこんな感じ

package main

import "fmt"

type User struct {
    Id             int
    Name, Location string
}

func (u *User) Greetings() string {
    return fmt.Sprintf("Hi %s from %s",
        u.Name, u.Location)
}

func NewUser(id int, name, location string) *User {
    id++
    return &User{id, name, location}
}

func main() {
    u := NewUser(42, "Matt", "LA")
    fmt.Println(u.Greetings())
}

can inline XXX

The compiler notices that it can inline the NewUser function defined on line 15 and inline it on line 21. Dave Cheney has a great post about why Go’s inlining is helping your programs run faster.

  • 関数XXXはインライン化の条件を満たしているからインライン化できるよ

inlining call to XXX

  • can inline XXX は、あくまで「関数 XXX がインライン化の条件を満たしているよ」と言っているだけで、実際にインライン化はされていない
  • inlining call to XXX は、関数 XXXの呼び出し箇所に対して、「実際に関数XXXの呼び出しをインライン化したよ」という意味

leaking param

On a few lines, you see the potentially alarming leaking param message. It doesn’t mean that there is a memory leak but that the param is kept alive even after returning. The “leaked params” are:

  • メモリリークじゃないから安心して
  • 関数が終わっても変数が生き続けるよ(golangだと関数内て定義した変数をreturnできる)

X argument does not escape

X argument does not escape means that the argument doesn’t “escape” the function, meaning that it’s not used outside of the function so it’s safe to store it on the stack.

  • 変数 X は関数内でしか使用されていない(からスタックに積めるよ)

X escapes to heap

On the other hand, you can see that &User literal escapes to heap. What it means is that the address of a literal value is used outside of the function and therefore can’t be stored on the stack. The value could be stored on the stack, except a pointer to the value escapes the function, so the value has to be moved to the heap to prevent the pointer referring to incorrect memory once the function returns. This is always the case when calling a method on a value and the method uses one or more fields.

  • 変数が関数外で使用されているからスタックに積めない(からヒープに移動するよ)

意外と好評なので追記

インライン化される条件については CompilerOptimizations · golang/go Wiki を参照のこと

Only short and simple functions are inlined. To be inlined a function must contain less than ~40 expressions and does not contain complex things like function calls, loops, labels, closures, panic's, recover's, select's, switch'es, etc.

  • 40 行程度より小さい関数じゃなきゃダメ
  • 下記が入っててもダメ
    • 関数呼び出し
    • ループ
    • ラベル
    • クロージャ
    • panic/recover
    • select
    • switch

結構厳しいなぁ...

52
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
52
29