ReadMeFirst
golangには、関数のbenchmarkを行うパッケージ・ユーティリティが標準で含まれています。
今回はgoで関数単位でのbenchmarkをとる方法について書きます。
testの基本的な実行方法については、前記事を参照。
ベンチマークするテスト関数を作る
testing package の benchMark用の
構造体を使います。
Benchmark関数は以下のように宣言します。(規約)
func BenchmarkXxx(b *testing.B)
- go界隈では有名な
appendで都度allocateすると重いよね~
なコードを例に。testファイルを作成
hoge_test.go
package main
import (
"fmt"
"testing"
)
func BenchmarkAppend_AllocateEveryTime(b *testing.B) {
base := []string{}
b.ResetTimer()
// Nはコマンド引数から与えられたベンチマーク時間から自動で計算される
for i := 0; i < b.N; i++ {
// 都度append
base = append(base, fmt.Sprintf("no%d", i))
}
}
func BenchmarkAppend_AllocateOnce(b *testing.B) {
//最初に長さを決める
base := make([]string, b.N)
b.ResetTimer()
// Nはコマンド引数から与えられたベンチマーク時間から自動で計算される
for i := 0; i < b.N; i++ {
base[i] = fmt.Sprintf("no%d", i)
}
}
実行
$ go test -bench . -benchmem
testing: warning: no tests to run
PASS
BenchmarkAppend_AllocateEveryTime-4 2000000 676 ns/op 106 B/op 2 allocs/op
BenchmarkAppend_AllocateOnce-4 5000000 258 ns/op 22 B/op 2 allocs/op
実行した回数
1回あたりの実行に掛かった時間(ns/op)
1回あたりのアロケーションで確保した容量(B/op)
1回あたりのアロケーション回数(allocs/op)
が表示されていますね。
毎回appendする場合と最初に固定長で用意する場合で大分速度と確保容量が違いますね。
知っとくと便利なオプション
https://golang.org/cmd/go/#hdr-Description_of_testing_flags
に載ってる中からよく使うものを抜粋。
- -benchmem
メモリ関連の情報を出力。
- -benchtime t
計測に使う時間をt
で指定する。defaultは1s
- -cpuprofile=*.prof
詳細なCPUプロファイルが取れる go tool pprof
で内容を見る
- -count
テストする回数を指定
- -cpu
実行するcpu数
- -memprofile=*.prof
詳細なMemoryプロファイルが取れる go tool pprof
で内容を見る
よく使うtesting.Bのmethod
コード見た方が早いぜ、って方はこちら
testing.B.ResetTimer()
計測時間をResetします。比べたい処理部分の前に行う感じで。
StartTimer(),StopTimer()もよく使います。
testing.B.Benchmark()
go testを使わないでBenchmarkをするときに。
返り値はこちら