概要
この記事は、CyberAgent PTA Advent Calendar 2022の12日目の記事です。
広告プロダクトチームでサーバーサイドエンジニアをやっています。
Golangの広告プロダクト実装において、システムパフォーマンスも意識しながら実装をしていたため、今回はGoにベンチマークテストについて書きます。
Go Benchmark
Goのtestingパッケージには、ベンチマークを行う機能が提供されています。
func BenchmarkXxx(*testing.B)
のように、関数の接頭辞にBenchmark
を付けることで、ベンチマークテスト用の関数として見なされます。
go test
に-bench
フラグを付けることで実行可能です。
ベンチマーク用関数のサンプルは下記で、
func BenchmarkRandInt(b *testing.B) {
for i := 0; i < b.N; i++ {
rand.Int()
}
}
b.N回実行されるようになっていて、
下記のような実行結果が出力されます。
BenchmarkRandInt-8 68453040 17.8 ns/op
ループあたり17.8nsの速度で、68453040回実行されたことを意味しています。
オプション
いくつかのオプションが用意されていて、より詳細な情報を出力することもできます。
-benchmem
はメモリの情報を出力できるので、おすすめ。
-cpu
, -benchtime
, -cpuprofile
などいくつかあります。
詳細はこちら: https://pkg.go.dev/cmd/go#hdr-Testing_flags
ベンチマークテストしてみる
import (
"fmt"
"strconv"
"testing"
)
func BenchmarkA(b *testing.B) {
for i := 0; i < b.N; i++ {
testA(i)
}
}
func BenchmarkB(b *testing.B) {
for i := 0; i < b.N; i++ {
testB(i)
}
}
func testA(num int) string {
return strconv.Itoa(num)
}
func testB(num int) string {
return fmt.Sprintf("%d", num)
}
strconv.Itoa
とfmt.Sprintf
を比較するテストを書いてみました。
go test -bench . -benchmem
で実行します。
BenchmarkA-8 47877226 24.79 ns/op 7 B/op 0 allocs/op
BenchmarkB-8 15777586 76.22 ns/op 16 B/op 1 allocs/op
strconv.Itoa
は、ループ当たり24.79nsの速度で、47877226回実行でき、
fmt.Sprintf
は、ループ当たり76.22nsの速度で、15777586回実行できたことが分かりました!