関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。たまに、使いたいときに忘れているのでここにメモメモ。。。
似た内容を以前にも記載しているのかもしれませんが、、。
ガッチリとデバッグしたい場合は「最適化」と「インライン化」を無効にしてビルドするのが定石です。
ガッチリとリリースビルドしたい場合は、「シンボル」と「DWARF(デバッグ情報)」を除去してビルドするのが定石です。
試してみる
ソースコード
実装内容に意味はないです。
package main import ( "io" "log" "sync" "time" ) func main() { log.SetFlags(0) log.SetOutput(io.Discard) if err := run(); err != nil { panic(err) } } // この関数は最適化が有効な場合、直接 v*2 になる可能性があり // インライン化が有効な場合、インライン化される可能性がある func calc(v int) int { v1 := v v2 := 2 return v1 * v2 } func run() error { const ( COUNT = 10000000 WORKERS = 4 ) var ( ch = make(chan int) wg sync.WaitGroup ) // producer wg.Add(1) go func(ch chan<- int) { defer wg.Done() defer close(ch) for i := range COUNT { ch <- calc(i) } }(ch) time.Sleep(10 * time.Millisecond) // consumer for range WORKERS { wg.Add(1) go func(ch <-chan int) { for v := range ch { log.Println(v) } }(ch) } wg.Done() return nil }
デバッグ
go build -gcflags "all=-N -l" -o debug main.go
オプションの意味
# gcflags の all=-N -l の意味 (goコンパイラに対しての指示) (go tool compile -help) # all= は全てのパッケージが対象という意味 # -N は最適化無効という意味 (No optimization) # -l はインライン化無効という意味 (No inlining)
リリース
go build -ldflags "-s -w" -o release main.go
オプションの意味
# ldflags の -s -w の意味 (リンカに対しての指示) (go tool link -help) # -s はシンボルテーブル削除という意味 # -w はDWARF情報削除という意味(デバッグ情報)
Taskfile.yml
# https://taskfile.dev version: '3' vars: RE1: main\.go.*inlining call.*$ tasks: default: cmds: # gcflags の all=-m -N -l の意味 (goコンパイラに対しての指示) (go tool compile -help) # all= は全てのパッケージが対象という意味 # -m はビルド時のコンパイラの詳細情報を出力せよという意味 # -N は最適化無効という意味 (No optimization) # -l はインライン化無効という意味 (No inlining) - cmd: go build -gcflags "all=-m -N -l" -o debug main.go 2>&1 | grep "{{.RE1}}" ignore_error: true - cmd: go build -gcflags "all=-m" -o normal main.go 2>&1 | grep "{{.RE1}}" ignore_error: true # ldflags の -s -w の意味 (リンカに対しての指示) (go tool link -help) # -s はシンボルテーブル削除という意味 # -w はDWARF情報削除という意味(デバッグ情報) - cmd: go build -gcflags "all=-m" -ldflags "-s -w" -o release main.go 2>&1 | grep "{{.RE1}}" ignore_error: true - ls -l {normal,debug,release} | awk 'NF>1 {print $5, $NF}'
実行すると以下のような感じです。
task: [default] go build -gcflags "all=-m -N -l" -o debug main.go 2>&1 | grep "main\.go.*inlining call.*$" task: [default] go build -gcflags "all=-m" -o normal main.go 2>&1 | grep "main\.go.*inlining call.*$" ./main.go:55:16: inlining call to log.Println ./main.go:60:9: inlining call to sync.(*WaitGroup).Done ./main.go:44:14: inlining call to calc ./main.go:40:16: inlining call to sync.(*WaitGroup).Done ./main.go:57:4: inlining call to run.func2 ./main.go:57:4: inlining call to log.Println ./main.go:11:14: inlining call to log.SetFlags ./main.go:12:15: inlining call to log.SetOutput ./main.go:11:14: inlining call to log.(*Logger).SetFlags ./main.go:11:14: inlining call to atomic.(*Int32).Store task: [default] go build -gcflags "all=-m" -ldflags "-s -w" -o release main.go 2>&1 | grep "main\.go.*inlining call.*$" ./main.go:55:16: inlining call to log.Println ./main.go:60:9: inlining call to sync.(*WaitGroup).Done ./main.go:44:14: inlining call to calc ./main.go:40:16: inlining call to sync.(*WaitGroup).Done ./main.go:57:4: inlining call to run.func2 ./main.go:57:4: inlining call to log.Println ./main.go:11:14: inlining call to log.SetFlags ./main.go:12:15: inlining call to log.SetOutput ./main.go:11:14: inlining call to log.(*Logger).SetFlags ./main.go:11:14: inlining call to atomic.(*Int32).Store task: [default] ls -l {normal,debug,release} | awk 'NF>1 {print $5, $NF}' 2279432 debug 2313124 normal 1503416 release
デバッグビルド用のフラグを設定した場合、インライン化が実施されていませんね。
何故か、通常時よりデバッグビルド用のフラグを設定した方が少しファイルサイズが減るのは謎。
参考情報
Goのおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。