Golangでベンチマークを取ってみた

  • 5
    Like
  • 0
    Comment
More than 1 year has passed since last update.

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に意味が書いてあるっぽいので読みましょう。

https://github.com/golang/tools/blob/master/benchmark/parse/parse.go#L28-L37

参考

Go でベンチマーク
go test で出来ること
Goでは文字列連結はコストの高い操作