ゴーファーさん、こんにちは?
このブログ投稿では、#golang testing パッケージに組み込まれた素晴らしいツールの使用方法を説明します。コードまたは関数のパフォーマンスをどのようにテストしますか? ベンチマーク テストを使用します。
行きましょう
このテストでは、次のように決定される古典的なフィボナッチ数またはフィボナッチ数列を使用します。
if (x < 2) F(0) = 1 F(2) = 2 else F(x) = F(x-1) + F(x-2) In practice, the sequence is: 1, 1, 2, 3, 5, 8, 13, etc.
この順序は、以下に示すように、数学や自然のいくつかの部分にも現れるため、重要です。
このコードを実装するにはいくつかの方法がありますが、ベンチマーク テストには再帰的計算方法と反復計算方法の 2 つを選択します。関数の主な目的は、位置を提供し、その位置のフィボナッチ数を返すことです。
// main.go func fibRecursive(n int) int { if n <= 2 { return 1 } return fibRecursive(n-1) + fibRecursive(n-2) }
// main.go func fibIterative(position uint) uint { slc := make([]uint, position) slc[0] = 1 slc[1] = 1 if position <= 2 { return 1 } var result, i uint for i = 2; i < position; i++ { result = slc[i-1] + slc[i-2] slc[i] = result } return result }
これらの方法は最適化されていませんが、テストの結果はたとえ少数であっても大きく異なります。これはテストでわかります。コードに従うには、ここをクリックしてください。
次に、ベンチマーク テストとして、_main_test.go ファイルにテストをいくつか書きましょう。 ベンチマーク に関する Golang のドキュメントを使用すると、次のようにテストする関数を作成できます:
// main_test.go // The key is to start every function you want to benchmark with the keyword Benchmark and use b *testing.B instead of t *testing.T as input func BenchmarkFibIterative(b *testing.B) { // Use this for-loop to ensure the code will behave correctly. // Now, you can put the function or piece of code you want to test for i := 0; i < b.N; i++ { fibIterative(uint(100)) } } // Same as above func BenchmarkFibRecursive(b *testing.B) { for i := 0; i < b.N; i++ { fibRecursive(100) } }
先に進む前に質問します: どちらが速いですか?
小さい数値 (10) と少し大きい数値 (80) に対してテストを実行してみましょう。 ベンチマーク テストを実行するには、次のコマンドを実行するだけです:
go test -bench=関数名
このコマンドについて詳しく知りたい場合は、ここを確認してください。
最初のテスト:position=10
//(fibIterative) Results: cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz BenchmarkFibIterative-8 24491042 42.50 ns/op PASS ok playground 1.651s
この画像を使って分析してみましょう:
画像によると、テストには 8 つのコアがあり、時間制限はありません (完了するまで実行されます)。タスクを完了するのに1.651秒かかりました。
==== Extra ==== We got 24,491,042 iterations (computations), and each iteration (op) took 42.50 ns. Doing some math, we can calculate how much time one op took: 42.50 ns/op with 1 ns = 1/1,000,000,000 s op ≈ 2.35270590588e-12 s ==== Extra ====
良い結果ですね。位置 10 の再帰関数を確認してみましょう:
// Results BenchmarkFibRecursive-8 6035011 187.8 ns/op PASS ok playground 1.882s
タスクを完了するのに 1.882 秒かかったことがわかります。
反復関数が数デシ秒の差で勝利しました。次のテストをもう 1 つ試してみましょう:
位置 50
// Results for the Iterative Function cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz BenchmarkFibIterative-8 27896118 45.37 ns/op PASS ok playground 2.876s // Results for the Recursive Function cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz BenchmarkFibRecursive-8 6365198 186.3 ns/op PASS ok playground 1.918s
うわー!再帰関数の方が高速になったのでしょうか?
少し大きな数字で終わりましょう。
位置 80
// Results for the Iterative Function cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz BenchmarkFibIterative-8 5102344 229.5 ns/op PASS ok playground 1.933s // Results for the Recursive Function // My poor PC couldn’t handle it, so I had to reduce the position to 50 just to get some results printed. cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz BenchmarkFibRecursive-8 1 44319299474 ns/op PASS ok playground 44.951s
その違いは大きいです。位置 80 の場合、反復アプローチには約 2 秒かかりました。位置 50 の場合、再帰関数には約 45 秒かかりました。これは、Golang プロジェクトの速度が低下し始めたときにコードのベンチマークを行うことの重要性を示しています。
実稼働コードの実行が遅い、または予測できないほど遅い場合は、この手法を pprof または組み込みテスト パッケージの他のツールと組み合わせて使用し、コードがどこで実行されているかを特定してテストできます。不十分な点とそれを最適化する方法。
補足: 見た目に美しいコードのすべてがパフォーマンスが高いわけではありません。
再帰関数を改善するより良い方法を見つけることはできますか? (ヒント: 動的プログラミングを使用してください)。この記事では、一部の数値が小さい場合、再帰戦略が優れている理由を説明します。
以上がGolang を使用したベンチマークの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。