Golangでどんな書き方をするのがいいのかパフォーマンスを指標にしてみよう!ということでベンチマークを取ってみました。
やり方
*_test.goでファイルを作成します。
今回は文字列連結のパフォーマンス計測がしたいので以下の感じのコードを書きます。
package main
import "testing"
func BenchmarkMemAllocBeforeCustom(b *testing.B) {
n := 10
b.ResetTimer()
for i := 0; i < b.N; i++ {
s := ""
for j := 0; j < n; j++ {
s = s + "alice"
}
}
}
func BenchmarkMemAllocCustom(b *testing.B) {
n := 10
b.ResetTimer()
for i := 0; i < b.N; i++ {
s := make([]byte, 0)
for j := 0; j < n; j++ {
s = append(s, "alice"...)
}
}
}
ベンチマークの実行
ベンチマークの実行は以下のコマンドで行います。
$ go test -bench .
PASS
BenchmarkMemAllocBeforeCustom-4 2000000 815 ns/op
BenchmarkMemAllocCustom-4 5000000 373 ns/op
ok bench-test 4.669s
他にもオプションつけたりできます。
$ go test -bench . -benchmem
PASS
BenchmarkMemAllocBeforeCustom-4 2000000 815 ns/op 336 B/op 9 allocs/op
BenchmarkMemAllocCustom-4 5000000 373 ns/op 120 B/op 4 allocs/op
ok bench-test 4.669s
なんか謎の数値が並んでますが、-benchmem
の結果を簡単に説明すると以下な感じです。
// 関数の実行回数、有用な結果が得られるまで実行される
// 多ければ多いほど良い
2000000
// 1回の実行にかかった時間
// 少ないほど良い
815 ns/op
// 実行ごとに割り当てられたメモリのサイズ
// 少ないほど良い
336 B/op
// 1回の実行でメモリアロケーションが行われた回数
// 少ないほど良い
9 allocs/op
ベンチマークの結果の見方が分からなくなったらこの辺のBenchmarkStructに意味が書いてあるっぽいので読みましょう。
[追記:2019/02/27]
Go1.12になったことでちょこっと変更が加わりました。
https://syossan.hateblo.jp/entry/2019/02/27/171156