関連記事
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)
}
}
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
)
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)
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
version: '3'
vars:
RE1: main\.go.*inlining call.*$
tasks:
default:
cmds:
- 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
- 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のおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。