BenchmarkDotNetの概要
こんな感じ
Method | Mean | Error | StdDev | Scaled | Allocated |
---|---|---|---|---|---|
Dictionary | 145.376 ns | 6.3041 ns | 0.3562 ns | 1.000 | 0 B |
Cache | 1.294 ns | 0.0947 ns | 0.0053 ns | 0.009 | 0 B |
Mean:平均、Error:誤差、StdDev:標準偏差、Scaled:基準値に対する倍率、Allocated:ヒープ上のメモリアロケーション
以下、公式のドキュメントから抜粋など。 Overview | BenchmarkDotNet
使い方
- Consoleアプリのプロジェクトを追加
- NuGetでBenchmarkDotNetをインストールする
- ベンチマーク取りたいメソッドを書く
- 実行するところとかはコピペしてくる
- Releaseビルドにしてデバッグなし実行(Ctrl+F5)
- Visual Studioやその他アプリをできるだけ終了して、直接exe起動した方が良い
- ノートPCでは電源設定でパフォーマンス最優先にする
有償版LINQPad上でもNuGetは使えるので動きます。ただしLINQPad自体のOptimize設定(=Releaseビルド設定)が必要なのでデバッグ実行されなくなることに注意
FAQ (Frequently asked questions) | BenchmarkDotNet
サンプル
Sample: IntroBasic | BenchmarkDotNet
私が書いてみたのはこちら。
GitHub - cactuaroid/BenchmarkDotNetSample
注意事項
値を使わない以下のようなコードを書いてしまうとJITの最適化で消されてしまう。
void Foo() { Math.Exp(1); }
ので、値を返すようにする。
double Foo() { return Math.Exp(1); }
Good Practices | BenchmarkDotNet
例えばこんな時に
機能
- パラメータ振ったり組み合わせたりできる
- 基準ケースを指定して比較できる
- ベンチマーク前後にSetup/Cleanupできる
- ユニットテストのTestInitialize等と同じ
- 計測結果の統計値を取れる
- 通常は実行時間の平均を調べる
- マイクロベンチマークではない場合は分布が広くなりがちなので、代わりにパーセンタイルを調べることも可能
- IL吐ける(コンパイラ比較用)
Parameterization | BenchmarkDotNet
内部の動き
- 設定に応じて独立したプロジェクトを生成
- 条件の組み合わせに応じてベンチマークプロセスを起動
- 下記の各処理が実行される
- Pilot:実行回数を決定する
- OverheadWarmup, OverheadWorkload:BenchmarkDotNet自身のオーバーヘッド評価
- ActualWarmup:対象メソッドのウォームアップ
- ActualWorkload:計測
- Result:計測結果の計算=ActualWorkload - 平均オーバーヘッド
- 結果出力