DUICUO

BenchmarkDotNet を .NET パフォーマンステストと最適化に使用する方法の詳細な説明

BenchmarkDotNetは、パフォーマンスベンチマーク用のオープンソースライブラリです。開発者が.NETアプリケーションのコードパフォーマンスをテストするのに役立ちます。様々なベンチマークタイプ、出力形式、カスタムパラメータ、統計情報、可視化をサポートし、テスト結果を自動的に分析して詳細なレポートを生成します。コードパフォーマンスを測定および分析するための、シンプルで使いやすく、強力なツールを提供することを目指しています。

BenchmarkDotNet の主な機能は次のとおりです。

シンプルで使いやすい: BenchmarkDotNetの使い方は非常にシンプルです。テスト対象のメソッドを含むクラスを定義し、これらのメソッドにBenchmark機能を追加するだけです。BenchmarkDotNetはこれらのメソッドを自動的に実行し、詳細なパフォーマンス分析レポートを提供します。

複数のテスト シナリオをサポート: BenchmarkDotNet は、メソッド レベルのベンチマーク テスト、クラス レベルのベンチマーク テスト、メモリ割り当てテスト、マルチスレッド テストなど、複数のテスト シナリオをサポートします。

強力な分析機能: BenchmarkDotNetは豊富な分析機能を備えており、平均実行時間、メモリ使用量、GC負荷など、様々なパフォーマンス指標レポートを生成します。また、テスト結果をCSV、JSON、Markdownなどの形式でエクスポートし、さらなる分析や比較に活用できます。

高度な設定が可能: BenchmarkDotNetは豊富な設定オプションを提供し、特定のニーズに合わせてテストを微調整できます。ユーザーは、テスト実行回数、反復回数、ウォームアップ時間などのパラメータを設定できるほか、様々なアナライザーやレポーターの有効化/無効化も行えます。

クロスプラットフォーム サポート: BenchmarkDotNet は、Windows、Linux、macOS などの複数のプラットフォームで実行でき、.NET Framework、.NET Core、Mono などの複数の異なるランタイムをサポートします。

次のセクションでは、BenchmarkDotNet の基本的な使い方と機能を紹介します。

インストールと設定

BenchmarkDotNet は、NuGet パッケージとしてプロジェクトにインストールできます。

 Install-Package BenchmarkDotNet <ItemGroup> <PackageReference Include="BenchmarkDotnet" Version="0.13.5" /> </ItemGroup>

インストール後、[MemoryDiagnoser] 属性と [Benchmark] 属性を使用して、パフォーマンスをテストする必要があるクラスをマークします。

 using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; [MemoryDiagnoser] public class MyBenchmark { [Benchmark] public void MyMethod1() { // test code } } class Program { static void Main(string[] args) { var summary = BenchmarkRunner.Run<MyBenchmark>(); } }

ベンチマークテストの種類

BenchmarkDotNet は、次のようなさまざまなベンチマーク タイプをサポートしています。

  • IterationBenchmark: 最も基本的なタイプのベンチマーク テスト。1 回の反復でコードの実行時間をテストするために使用されます。
  • 操作ベンチマーク: 指定された時間内に操作を繰り返し実行し、各操作の実行時間を計算します。
  • パラメトリックベンチマークは、異なるパラメータまたはデータセットにおける実行時間をテストするために使用されます。パラメータは属性を通じて指定できます。
  • マイクロベンチマーク: 配列要素へのアクセス速度など、小さなコード スニペットをテストするために特別に設計されています。

実際のテストでは、開発者はニーズやテストシナリオに基づいて様々なテストタイプを選択し、BenchmarkDotNetが提供するAPIとプロパティを使用して設定を行います。例えば、テストの反復回数、データサイズ、実行モードなどのパラメータを設定することで、テスト結果の精度と信頼性を高めることができます

SimpleJobは、ベンチマークテストのパラメータを指定するために使用されるBenchmarkDotNetのプロパティです。以下はSimpleJobプロパティの詳細な説明です。

  • RunStrategy: BenchmarkDotNetがベンチマークテストを実行するための戦略を指定します。指定可能な値は、ColdStart、Throughput、Monitoringです。デフォルト値はThroughputです。
  • LaunchCount: 各テスト反復の前に起動されるプロセスの数。デフォルト値は1です。
  • WarmupCount: テスト反復ごとのウォームアップ回数。デフォルト値は 5 です。
  • TargetCount: 各テスト反復で実行されるターゲット操作の数。デフォルト値は10です。
  • InvocationCount: 各テスト反復で操作が実行される回数。デフォルト値は1です。
  • IterationTime: 反復処理の最大継続時間を秒単位で指定します。デフォルト値は1000ミリ秒です。
  • MaxIterationCount: 実行する反復の最大回数を指定します。デフォルト値は 100 です。
  • MaxWarmupIterationCount: ウォームアップ反復の最大回数を指定します。デフォルト値は10です。
  • アフィニティ: スレッドを特定のCPUコアにバインドします。指定可能な値は「なし」、「すべて」、「偶数」、「奇数」です。デフォルト値は「なし」です。
  • Jit: コンパイラのバージョンを指定します。オプション値はLegacyJit、RyuJit、またはAutoです。デフォルト値はAutoです。
  • プラットフォーム: ベンチマークを実行するプロセスのCPUアーキテクチャを指定します。オプションの値はAnyCpu、X64、またはX86です。デフォルト値はAnyCpuです。
  • ランタイム: ベンチマークに使用するランタイムプラットフォームを指定します。オプションの値はCore、Clr、またはMonoです。デフォルト値はCoreです。
  • TargetFrameworkMoniker: .NET Framework 4.5、.NET Core 3.1 など、ベンチマーク テストに使用する .NET Framework のバージョンを指定します。
  • BaselineSwitch: ベンチマークテストをベースラインテストとして実行するかどうかを示すコマンドラインスイッチを指定します。デフォルト値は false です。
  • EnvironmentVariables: ベンチマーク プロセスに渡される環境変数の辞書が含まれます。
  • カテゴリ: ベンチマーク レポートでテストをグループ化するカテゴリのリストを指定します。

クラスに [SimpleJob] 属性をマークし、対応するテスト タイプを指定します。

 using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Jobs; [SimpleJob(RuntimeMoniker.NetCoreApp50, baseline: true)] [SimpleJob(RuntimeMoniker.NetCoreApp31)] [SimpleJob(RuntimeMoniker.Net472)] public class MyBenchmark { // test methods }

出力形式

BenchmarkDotNet は、次のような複数の出力形式をサポートしています。

  • 簡潔: テスト名、平均、標準偏差などの統計データを含む簡潔な概要情報を出力します。
  • デフォルト: テスト名、テスト方法、平均値、標準偏差などの統計データ、生のテスト データ、スループットと分布チャートなどを含む詳細なテスト結果を出力します。
  • Csv: テスト結果を CSV 形式で出力し、後で簡単に処理および比較できるようにします。
  • Html: カスタム形式、スタイル、インタラクティブ効果をサポートする HTML 形式でテスト結果を出力します。
  • RPlot: R 言語のスクリプトとグラフを出力し、高度な統計および視覚化分析を容易にします。

クラスに [MarkdownExporterAttribute.Default] などの属性を使用してマークし、対応する出力形式を指定できます。

 using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Exporters; using BenchmarkDotNet.Loggers; [MarkdownExporterAttribute.Default] [HtmlExporter] [AsciiDocExporter] public class MyBenchmark { // test methods }

カスタムパラメータ

BenchmarkDotNet は、次のようなさまざまなカスタム パラメータをサポートしています。

  • ジョブ: ランタイム バージョン、プラットフォーム、ガベージ コレクターなど、テストを実行するための環境と条件を指定します。
  • IterationCount: より正確なデータ ポイントと安定した統計を取得するために、各テストの反復回数を指定します。
  • WarmupCount: JIT コンパイラがランタイム環境をウォームアップできるように、各テストのウォームアップ回数を指定します。
  • LaunchCount: 瞬間的な起動時間の影響を排除するために、テストごとの起動回数を指定します。
  • 精度: テスト結果の精度と精密度を指定します。
  • ベースライン: 比較オブジェクトとして使用するベンチマーク方法を指定します。
  • 順序: テスト メソッドの実行順序を指定します。

クラスの [Params]、[ParamsSource]、または [ArgumentsSource] 属性を使用して、対応するパラメータを指定できます。

 using System.Collections.Generic; using BenchmarkDotNet.Attributes; public class MyBenchmark { [Params(10, 100, 1000)] public int N; [ParamsSource(nameof(GetData))] public int Data; public IEnumerable<int> GetData() => new[] { 1, 2, 3 }; [ArgumentsSource(nameof(GetParams))] public void MyMethod(int x, int y) { // test code } public IEnumerable<object[]> GetParams() => new List<object[]> { new object[] { 1, 2 }, new object[] { 3, 4 }, new object[] { 5, 6 } }; }

統計データと視覚化

BenchmarkDotNet はテスト結果を自動的に分析し、次のようなさまざまな統計データと視覚化を生成します。

  • 平均: 母集団の中心傾向レベルを表す平均値。
  • StdDev: 標準偏差。母集団の分散と安定性を示します。
  • 中央値: 並べ替え後の中央値。
  • Q1/Q3: ソート後の上位/下位四半期位置の値を表す、第 1/3/四半期の桁。
  • 最大/最小: ソート後の極値を表す最大値/最小値。
  • パーセンタイル: パーセンタイルは、ソート後の特定の位置にある値を表します。
  • ヒストグラム: ヒストグラムはテスト結果の頻度分布を表します。
  • 箱ひげ図: テスト結果と外れ値の 5 つの要約統計を表す箱ひげ図。
  • 概要: このセクションでは、テスト結果の主要な統計データと信頼区間を示します。

テストを実行した後、コンソール出力と生成されたレポート ファイルを表示して、テスト結果の詳細情報と分析結果を把握できます。

実際のケーススタディ

以下は、BenchmarkDotNet を使用したバブル ソートとクイック ソートのパフォーマンス テストの例です。

 using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; using System; public class SortingBenchmark { private int[] array; [Params(1000, 10000, 100000)] // 定义不同规模的数组作为参数public int ArraySize { get; set; } [GlobalSetup] public void Setup() { // 初始化待排序的数组array = new int[ArraySize]; Random random = new Random(); for (int i = 0; i < ArraySize; i++) { array[i] = random.Next(); } } [Benchmark] public void BubbleSort() { // 冒泡排序算法实现for (int i = 0; i < ArraySize - 1; i++) { for (int j = 0; j < ArraySize - i - 1; j++) { if (array[j] > array[j + 1]) { int temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; } } } } [Benchmark] public void QuickSort() { // 快速排序算法实现QuickSort(array, 0, ArraySize - 1); } private void QuickSort(int[] arr, int low, int high) { if (low < high) { int pivot = Partition(arr, low, high); QuickSort(arr, low, pivot - 1); QuickSort(arr, pivot + 1, high); } } private int Partition(int[] arr, int low, int high) { int pivot = arr[high]; int i = low - 1; for (int j = low; j < high; j++) { if (arr[j] < pivot) { i++; int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } int temp2 = arr[i + 1]; arr[i + 1] = arr[high]; arr[high] = temp2; return i + 1; } } public class Program { public static void Main(string[] args) { var summary = BenchmarkRunner.Run<SortingBenchmark>(); } }

上記の例では、まず`SortingBenchmark`というクラスを定義し、`Params`属性を使用して異なるサイズの配列をパラメータとして定義しました。次に、`GlobalSetup`メソッドで、ソートする配列を初期化しました。

次に、「Benchmark」機能を使用して、バブルソートとクイックソートのテストメソッド「BubbleSort」と「QuickSort」をそれぞれマークしました。これらの2つのメソッドには、それぞれバブルソートとクイックソートのアルゴリズムを実装しました。

最後に、`Main` メソッドで、`BenchmarkRunner.Run` メソッドを使用してベンチマーク テストを実行し、パフォーマンス分析レポートを生成します。

上記のコードを実行すると、BenchmarkDotNetはバブルソートとクイックソートのテストメソッドを自動的に実行し、パフォーマンス分析レポートを含む出力を生成します。必要に応じて配列サイズやその他の設定パラメータを調整することで、より詳細なパフォーマンス分析結果を得ることができます。

さらに、BenchmarkDotnet はパフォーマンス テストの結果ファイルを出力ディレクトリに出力します。

HTML バージョンを開くと、先ほどコンソールに表示されたものと同じものが表示されます。

上記はBenchmarkDotNetの基本的な使用方法と機能についてです。BenchmarkDotNetは豊富なAPIとパラメータ調整オプションを提供し、高度なパフォーマンス分析と可視化を可能にします。開発者がコードを最適化・改善し、アプリケーションのパフォーマンスと安定性を向上させるのに役立ちます。