Goプログラムでの実行時間の測定

Goアプリケーションを開発するとき、またはそれを改善する方法を見つけるためにベンチマークするときの一般的な操作は、関数の実行時間のベンチマークです。のトピックを紹介しましたGoでのCPUとメモリのプロファイリングすでにですが、これは異なり、アドホック関数の実行時間の測定に適しています。

2つの式の間の時間間隔を決定します。time.Since

time.Sinceによって提供される機能ですtimeをとる標準ライブラリパッケージTime値、現在の時刻との差を計算し、Duration値。これは、int64タイプであり、String()添付されたメソッド。計算された時間に人間にわかりやすい表記を提供します。

import (
    "fmt"
    "time"
)

func main() { start := time.Now()

<span style="color:#75715e">//... do something

fmt.Println(time.Since(start)) }

内部的には、time.Sinceの省略形ですtime.Now().Sub(t)

使用するdefer関数内の時間を測定する

を使用してこれを抽象化できますdefer

package main

import ( “log” “time” )

func runningtime(s string) (string, time.Time) { log.Println("Start: ", s) return s, time.Now() }

func track(s string, startTime time.Time) { endTime := time.Now() log.Println("End: ", s, “took”, endTime.Sub(startTime)) }

func execute() { defer track(runningtime(“execute”)) time.Sleep(3 * time.Second) }

func main() { execute() }

関数のパフォーマンスを複数回実行してベンチマークします。testingパッケージ

これは私が書いた簡単なライブラリで、文字列内のルーンの数を数えます。

runecount.go

package runecount

import “unicode/utf8”

func RuneCount(s string) int { return len([]rune(s)) }

func RuneCount2(s string) int { return utf8.RuneCountInString(s) }

文字列内のルーンを数える2つの方法のどちらが速いですか?ベンチマークを書くことでわかります。ベンチマークはに住んでいます*_test.goファイルは、通常のテストと同様に、で始まるテスト方法でライブを維持できます。Test*、しかし彼らはBenchmark*代わりに:

runecount_test.go

package runecount

import “testing”

func BenchmarkRuneCount(b testing.B) { s := “Gophers are amazing 😁” for i := 0; i < b.N; i++ { RuneCount(s) } } func BenchmarkRuneCount2(b testing.B) { s := “Gophers are amazing 😁” for i := 0; i < b.N; i++ { RuneCount2(s) } }

これは、ファイルが配置されているのと同じフォルダーで実行して実行します。

go test -bench=.

これにより、すべてのベンチマークが実行されます。取得したファイルは1つだけですが、ファイルが多数ある場合は、実行するファイルを指定できます。

各ベンチマークは、平均が結果を決定するのに十分安定するまで、ベンチマークランナーによって自動的に決定されるbN変数を渡すループを実行します。

これは私のMacで得られる出力です:

# flavio @ Flavios-MacBook-Pro in ~/go/src/github.com/flaviocopes/snippets/benchmark on git:master x [18:32:26]
$ go test -bench=.
BenchmarkRuneCount-2            20000000               115 ns/op
BenchmarkRuneCount2-2           30000000                44.1 ns/op
PASS
ok      github.com/flaviocopes/snippets/benchmark       3.812s

20000000そして30000000実行された操作の数です。

コマンドはベンチマーク結果を返します:それは2000万回実行されましたRuneCount()、平均163ナノ秒かかり、その後3,000万回実行されましたRuneCount2()、各反復で平均74.2ナノ秒かかりました。

そうBenchmark1、実行されますRuneCount()、より2倍遅いRuneCount2()、組み込みを使用しますutf8.RuneCountInString関数。ここでは驚きはありません。utf8.RuneCountInStringこの特定のタスク用に高度に最適化されています。


使用する代わりにgo test、電話することもできますtesting.Benchmarkコマンドから:

package main

import ( “fmt” “testing” “runecount” )

func BenchmarkRuneCount(b testing.B) { s := “Gophers are amazing 😁” for i := 0; i < b.N; i++ { RuneCount(s) } } func BenchmarkRuneCount2(b testing.B) { s := “Gophers are amazing 😁” for i := 0; i < b.N; i++ { RuneCount2(s) } }

func main() { fmt.Println(testing.Benchmark(BenchmarkRuneCount)) fmt.Println(testing.Benchmark(BenchmarkRuneCount2)) }

続きを読む場所


その他のチュートリアル: