gotesplitにAdd -race to list when it is specified for test optionsというPullRequestを投げたのだが、この背景を書いておこうと思う。
まずGoでは-race
オプションについて、以下のような挙動を起こす。
-race
フラグをつけるとruntime/raceがおそらく一番依存の深いところに追加されてコンパイルされるっぽい?- そのため、
go test
とgo test -race
はビルドキャッシュが全く異なる。つまりgo test
のビルドキャッシュはgo test -race
のビルドに全く使われないし、その逆も同じである
gotesplitの以前のバージョンでは、-race
オプションを付けても、テスト分割のためのテスト一覧を取得するgo test -list
コマンドのオプションには-race
をつけていなかった。このためgotesplitを使って-race
付きのテストをしようとすると、テスト一覧を取得する時に一度-race
なしのフルコンパイルが走り、実際のテスト実行で-race
ありのフルコンパイルが走っていた。フルコンパイルが2回走っていたので、想定以上の実行時間がかかってしまっていた。
上記のPullRequestによって、-race
がついていてもコンパイルは一度で済むようになったため高速化した。
挙動の調査ログ
https://github.com/shibayu36/go-playground のレポジトリを使って挙動を調査したログを貼っておく。
まずgo clean -cacheを使って完全にビルドキャッシュを飛ばした時、ビルドキャッシュのディレクトリのサイズはほぼ空になる。
$ go clean -cache $ du -sh /Users/shibayu36/Library/Caches/go-build 12K /Users/shibayu36/Library/Caches/go-build
その後、-race
なしで./playgroundのテストを実行してみる。この時166packageのコンパイルが走り、ビルドキャッシュが91Mになる様子が観察できる。
# -x付きで実際にコンパイルされるpackageを出す $ go test -count 1 -x ./playground 2>log.txt # コンパイルされたpackage数を出すoneliner $ grep "/compile " log.txt | awk -F'-p ' '{split($2, a, " "); print a[1]}' | wc -l 166 # ビルドキャッシュのサイズ $ du -sh /Users/shibayu36/Library/Caches/go-build 91M /Users/shibayu36/Library/Caches/go-build
もちろんもう一度同じコマンドを実行しても、ビルドキャッシュが利用されてコンパイルは一切行わない。
$ go test -count 1 -x ./playground 2>log-retest.txt $ grep "/compile " log-retest.txt | awk -F'-p ' '{split($2, a, " "); print a[1]}' | wc -l 0 $ du -sh /Users/shibayu36/Library/Caches/go-build 91M /Users/shibayu36/Library/Caches/go-build
このビルドキャッシュが存在する状態で-race
付きでテストすると、167packageのコンパイルが走ることがわかる。167packageというのは、ビルドキャッシュなしの状態で-race
なしのコンパイルしたpackage数+1の数字である。またビルドキャッシュのサイズが2倍以上に膨らみ、188Mになっている。
$ go test -race -count 1 -x ./playground 2>log-race.txt $ grep "/compile " log-race.txt | awk -F'-p ' '{split($2, a, " "); print a[1]}' | wc -l 167 $ du -sh /Users/shibayu36/Library/Caches/go-build 188M /Users/shibayu36/Library/Caches/go-build
さらにもう一度同じコマンドを実行しても、-race
用のビルドキャッシュが利用されてコンパイルは行われないように見える。
$ go test -race -count 1 -x ./playground 2>log-race-retest.txt $ grep "/compile " log-race-retest.txt | awk -F'-p ' '{split($2, a, " "); print a[1]}' | wc -l 0 $ du -sh /Users/shibayu36/Library/Caches/go-build 188M /Users/shibayu36/Library/Caches/go-build
さらに-race
付きだと何のpackageが1つ増えているかを調査するために次のコマンドを実行する。するとruntime/raceが追加でコンパイルされていることが分かる。
diff -u <(grep "/compile " log.txt | awk -F'-p ' '{split($2, a, " "); print a[1]}' | sort) <(grep "/compile " log-race.txt | awk -F'-p ' '{split($2, a, " "); print a[1]}' | sort)
--- /dev/fd/11 2023-09-26 09:43:17 +++ /dev/fd/12 2023-09-26 09:43:17 @@ -133,6 +133,7 @@ runtime/internal/math runtime/internal/sys runtime/pprof +runtime/race runtime/trace sort strconv
ということでraceオプションの有無で、完全にビルドキャッシュが分かれている挙動を確認できました。