Go言語では、testingパッケージに用意されているBenchmark関数を使って性能測定することができます。
参考
書き方・実行方法
ベンチマーク関数は「BenchmarkXxx」という名前で定義します。接頭語に「Benchmark」、その後に測定したい関数名が続くというルールです。
echo
という関数のベンチマークを計測する場合には、次のようになります。
echo_test.go
ファイル
package main import "testing" func BenchmarkEcho(b *testing.B) { for i := 0; i < b.N; i++ { echo() } }
for文に出てくる b.N
は実行回数です。自動で、Nの小さな値を使って測定を行い、その後安定した時間の計測ができるだけの十分な値を推定してくれます。
実行方法は、
- パッケージ内の全てのベンチマークを計測したい場合、
go test -bench=.
- 特定の関数のベンチマークのみを計測したい場合、
go test -bench=Xxx
(例. go test -bench=Echo)
実際にベンチマークを計測してみる
まずは、計測対象の関数を用意します。
文字列のスライスを受け取り、半角スペース区切りの1つの文字列にする関数を2パターン実装しています。forループを使うものと、strings.Joinを使うものです。
main.go
package main import ( "fmt" "os" "strings" ) func main() { fmt.Println("loop echo") fmt.Println(loopEcho(os.Args[1:])) fmt.Println("join echo") fmt.Println(joinEcho(os.Args[1:])) } func joinEcho(args []string) string { return strings.Join(args, " ") } func loopEcho(args []string) string { s, sep := "", "" for _, arg := range args { s += sep + arg sep = " " } return s }
これに対して、Benchmark
関数を書いていきます。
main_test.go
package main import "testing" var args = []string{"echo", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"} func BenchmarkLoopEcho(b *testing.B) { for i := 0; i < b.N; i++ { loopEcho(args) } } func BenchmarkJoinEcho(b *testing.B) { for i := 0; i < b.N; i++ { joinEcho(args) } }
実行
go test -bench=. -benchmem
で実行します。(-benchmem
はメモリ割り当ての情報を追加するオプション)
strings.Join
を使った方が処理時間、メモリ量、メモリ割り当ての回数全てにおいて高パフォーマンスであることがわかりました。
【おすすめ図書】プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)