ベンチマーク入門
Goのベンチマークは多くの点で単体テストに似ていますが、キーの違いがあり、異なる目的に役立ちます.囲碁での単体テストとして知られていないので、この記事はGoのベンチマークを紹介することを目的としています:どのように作成するには、どのようにそれらを実行するには、どのように結果を読むといくつかの高度なトピックにいくつかのポインタは、外出先でベンチマークテストを作成する.
ベンチマークは、Goコードのパフォーマンスをテストする関数です
testing
標準ライブラリのパッケージは、このように外部ライブラリに任意の依存関係なしで利用可能です.ベンチマークを実行するとき、あなたは実行時に関する若干の情報と要求されるならば、ベンチマークの下のコードのメモリフットプリントを提供します.
$go test -benchmem -run ^$ -bench ^(Benchmark1Sort)$
goos: linux
goarch: amd64
Benchmark1Sort-12 10000 105705 ns/op 8224 B/op 2 allocs/op
PASS
ok _/home/mcaci/code/github.com/mcaci/dev-art/go-bench 1.083s
でベンチマークを作成する
ベンチマークを作成するには
testing
パッケージを作成し、テスト関数が作成されるような方法でベンチマーク関数を作成します.たとえば、単体テストを定義するとき、
func TestAny(t *testing)
初めに、代わりに、ベンチマークを定義するとき、私たちはfunc BenchmarkAny(b *testing.B)
.ユニットテストに関するGoのベンチマークの顕著な違いは、0から0までのループです
b.N
. ベンチマークの下でコードの性能測定の精度を向上させるのに十分なデータが集められることを確認するために、ベンチマークは複数回実行されます.野原
b.N
固定値ではありませんが、ベンチマーク関数が少なくとも1秒間実行されるように動的に適応されます.ここでは、ベンチマークとテスト関数の比較を示します.
func Benchmark1Sort(b *testing.B) {
for i := 0; i < b.N; i++ {
sort.Ints(generateSlice(1000))
}
}
func Test1Sort(t *testing.T) {
slice := generateSlice(1000)
if len(slice) != 1000 {
t.Errorf("unexpected slice size: %d", len(slice))
}
}
ベンチマークの実行
goのベンチマークを実行するための出発点は
go test
コマンドとここで我々は我々がユニットテストを実行していないことを確認するために必要なものが表示されます.基本的な使い方
go test -bench .
単独で.go test
ユニットテストのみを実行するので、フラグを追加する必要があります-bench
go testを指示してベンチマークも実行します.具体的には、このコマンドは、現在のパッケージ内のすべての単体テストとベンチマークを実行します.の引数として追加されました
-bench
フラグ."\"値は実際にどのようなベンチマークを実行するかを記述できる正規表現です.例えば
go test -bench ^Benchmark1Sort$
ベンチマーク1 sortという名前のベンチマークを実行します.ユニットテストを実行するときと同じように、
-v
VERBOSE用のフラグは、任意の印刷出力と同様に実行されるベンチマークの詳細を表示します.などのパスを追加したり、パスを追加したりします("//..."特定のパッケージ(またはすべてのパッケージとサブパッケージ)のベンチマークを探す.go test -bench . -v
go test -bench . ./...
ベンチマークのみの実行
すべての単体テストをフィルタアウトする
go test
's実行-run ^$
フラグを使用する.go test -run ^$ -bench .
旗-run
単独でどの単位テストを実行すべきかを指定するために使用されます.引数は正規表現です.使用するとき^$
引数として、現在のパッケージに存在するベンチマークだけを実行するすべてのテストを効果的にフィルタリングします.複数回走る
単に
-count
パラメータを指定された数回何度も実行します.すべての実行結果が出力されます.$ go test -bench ^Benchmark1Sort$ -run ^$ -count 4
goos: linux
goarch: amd64
Benchmark1Sort-12 10207 134834 ns/op
Benchmark1Sort-12 7554 175572 ns/op
Benchmark1Sort-12 7904 148960 ns/op
Benchmark1Sort-12 8568 147594 ns/op
PASS
ok _/home/mcaci/code/github.com/mcaci/dev-art/go-bench 7.339s
このフラグは、ベンチマークデータの統計解析を行うために、複数の実行結果をサンプリングするときに便利です.ベンチマーク結果の読み込み
次の例をもう一度取りましょう
go test -bench
出力を調べる.func Benchmark1Sort(b *testing.B) {
for i := 0; i < b.N; i++ {
sort.Ints(generateSlice(1000))
}
}
実行時に
最初の解析のためにベンチマークを実行します
go test -bench ^Benchmark1Sort$ -run ^$
$ go test -bench ^Benchmark1Sort$ -run ^$
goos: linux
goarch: amd64
Benchmark1Sort-12 9252 110547 ns/op
PASS
ok _/home/mcaci/code/github.com/mcaci/dev-art/go-bench 1.053s
出力された出力は、任意のベンチマーク実行に存在します.go env GOOS GOARCH
(大文字小文字を区別する)sort.Ints(generateSlice(1000))
, この場合は、10547 ns/opとなる.-cpu
フラッグベンチマークは、フラグで定義されたCPUごとに1回複数回実行されます.$ go test -bench ^Benchmark1Sort$ -run ^$ -cpu 1,2,4
goos: linux
goarch: amd64
Benchmark1Sort 9280 113086 ns/op
Benchmark1Sort-2 9379 117156 ns/op
Benchmark1Sort-4 8637 118818 ns/op
PASS
ok _/home/mcaci/code/github.com/mcaci/dev-art/go-bench 3.234s
このフラグが省略された場合、デフォルト値はGo変数GOMaxProcsから取られ、CPUの数は1に等しいときに出力されません.実行時とメモリ
出力にメモリフットプリントに関する情報を追加するには、
-benchmem
フラグは以下の通り.$ go test -bench ^Benchmark1Sort$ -run ^$ -benchmem
goos: linux
goarch: amd64
Benchmark1Sort-12 10327 116903 ns/op 8224 B/op 2 allocs/op
PASS
ok _/home/mcaci/code/github.com/mcaci/dev-art/go-bench 2.128s
つの新しい列がベンチマーク列の出力に追加されましたより複雑なベンチマークを書く
ここでは、より複雑なベンチマークを書く方法のいくつかの例があります.
StartTimer / stoptimer / resettimer
ベンチマークにコードを実行するために費やされる時間を実際に測定する前にいくつかのセットアップをする必要があるときに
StartTimer
, StopTimer
and ResetTimer
実際にはベンチマークツールによって考慮される必要があるコードのビットを分離するのに役立ちます.前のスニペットを取り、ソート操作からスライスの作成を分離し、後者の実行を測定します.
こうするには、
func Benchmark2aSort(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
s := generateSlice(1000)
b.StartTimer()
sort.Ints(s)
}
}
使用によってb.StopTimer()
我々は、実行時にこの時点からベンチマークの一部となることはありませんb.StartTimer()
が呼び出されると、各ループでは、sort.Ints(s)
ベンチマーク.最初にスライスを準備し、ベンチマークのための不変量を作りたいなら、代わりに書くことができます.
func Benchmark2bSort(b *testing.B) {
s := generateSlice(1000)
b.ResetTimer()
for i := 0; i < b.N; i++ {
sort.Ints(s)
}
}
使用によってb.ResetTimer()
我々はこれまで収集したすべてのデータを破棄し、新たにベンチマークのためのデータの収集を開始し、効果的にgenerateSlice
結果全体を呼び出します.ベンチマークテストケースとサブベンチマーク
テストのように、ベンチマークもサブベンチャマークを作成するテストケースと実行ループの構造から恩恵を受けることができます.
例を見ましょう.
func Benchmark3Sort(b *testing.B) {
benchData := map[string]struct {
size int
}{
"with size 1000": {size: 1000},
"with size 10000": {size: 10000},
"with size 100000": {size: 100000},
"with size 1000000": {size: 1000000},
}
b.ResetTimer()
for benchName, data := range benchData {
b.StopTimer()
s := generateSlice(data.size)
b.StartTimer()
b.Run(benchName, func(b *testing.B) {
for i := 0; i < b.N; i++ {
sort.Ints(s)
}
})
}
}
この例ではmap[string]struct{...}
テストケースを使った複雑なテストのために、ベンチマークの例とデータを定義し、b.Run(name string, f func(*testing.B))
ベンチマークテストを別々に実行するサブベンチマークを作成します.$ go test -bench ^Benchmark3Sort$ -run ^$
goos: linux
goarch: amd64
Benchmark3Sort/with_size_1000000-12 10 130396565 ns/op
Benchmark3Sort/with_size_1000-12 23210 58078 ns/op
Benchmark3Sort/with_size_10000-12 1300 865703 ns/op
Benchmark3Sort/with_size_100000-12 118 8718656 ns/op
PASS
ok _/home/mcaci/code/github.com/mcaci/dev-art/go-bench 6.670s
ベンチマークの名前がベンチマークの名前を出力するベンチマークの名前/ベンチマークとしてベンチマーク名に追加されます.考えを捨てる
ベンチマークがどのように働いているかを説明し、効果的にそれらを書く方法のより深い知識を得るためにまだ長い道のりがあります.それ自身の記事を必要とする主要なトピックのうちの1つは
b.RunParallel
しかし、私はこの記事がGoでベンチマークの基礎を与えるのに役立つことを望みます、そして、機能とツールをここで言及していないツールを調査する若干の理由.あなたはTwitterで@ iKiForosCount freesまたはここでdev . toを見つけることができます
そして、私はあなたの質問やコメントを聞くのを楽しみにしています.
これはミリー、読書のおかげだった!
参考文献
Go's testing package and go cmd testing flags GOチームから
Justforfunc 'によるベンチマークに関する記事
Reference
この問題について(ベンチマーク入門), 我々は、より多くの情報をここで見つけました https://dev.to/mcaci/introduction-to-benchmarks-in-go-3ciiテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol