寝ても覚めてもこんぴうた

プログラム書いたり、ネットワーク設計したり、サーバ構築したり、車いじったり、ゲームしたり。そんなひとにわたしはなりたい。 投げ銭は kyash_id : chidakiyo マデ

Goでmain関数経由でもベンチマークする

f:id:chidakiyo:20191206192054j:plain

Goはテストの機能としてベンチマークを測定する機能が標準で提供されています。
ただ、そのままだとテストコードを実行できる環境でしか実行ができなかったりするため、 main関数から実行したい場合もあるかと思います。

今回はmainからベンチマークを実行できる機能を調べてみました。
Goが標準に提供しており、Appengine上で実行するなどの目的で使えます。

通常のベンチマーク

通常のテストコードから実行するベンチマークは以下のような感じですね

package main

import (
  "testing"
    "time"
)

func Benchmark_Sample(b *testing.B) {
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        // 遅い処理
        time.Sleep(10 * time.Millisecond)
    }
}
go test -bench . -benchmem

という感じに実行すると以下のような結果が表示されます。

Benchmark_Sample-12          100          11565214 ns/op               4 B/op          0 allocs/op

見方はこの記事では特に説明しません。

mainから実行するベンチマーク

mainから実行する場合には testing.Benchmark が利用できます。
コードを見たほうが速いと思うので以下のようになります

package main

import (
    "testing"
    "time"
  "fmt"
)

func main() {
    result := testing.Benchmark(func(b *testing.B) {
        b.ResetTimer()
    for i := 0; i < b.N; i++ {
          // 遅い処理
          time.Sleep(10 * time.Millisecond)
      }
    })
    fmt.Printf("%s", result)
}

ほぼ見覚えのある形なので、特に違和感はないと思います。
テストとして実行するベンチマークと異なる点としては、 testing.Benchmark の戻り値の BenchmarkResult を利用してベンチマーク結果を取得するという点です。

BenchmarkResultString() 関数がよしなに実装されているので、適当にPrintしても以下のような感じで表示されます。

934     1275190 ns/op

その他の情報も細かく見たい人は、 BenchmarkResult の中の値を適切に表示すれば良いと思います。

まとめ

こんな感じで、テストコードとしてではなく、Goのmainから実行された処理の中でベンチマークが実行できるようになります。
おそらく嬉しい人は嬉しいのでは。

では、また。