More than 1 year has passed since last update.


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をするときに。

返り値はこちら


参考

testing package

go cmd


関連

はじめてのgo test