BenchmarkDotNet是一個用于進行性能基準測試的開源庫,可以幫助開發者在.NET 應用程式中測試代碼性能。它支援多種基準測試類型、輸出格式、自定義參數、統計資料和可視化效果,并且對測試結果進行自動分析,生成詳細的報告。旨在提供一個簡單易用且功能強大的工具來測量和分析代碼的性能。
BenchmarkDotNet具有以下主要特點:
1. 簡單易用:使用BenchmarkDotNet非常簡單,隻需定義一個包含待測試方法的類,并使用Benchmark特性标記這些方法。BenchmarkDotNet将自動運作這些方法,并提供詳細的性能分析報告。
2. 支援多種測試場景:BenchmarkDotNet支援多種測試場景,包括方法級别的基準測試、類級别的基準測試、記憶體配置設定測試、多線程測試等。
3. 強大的分析功能:BenchmarkDotNet提供了豐富的分析功能,可以生成各種性能名額報告,如平均執行時間、記憶體使用情況、GC壓力等。它還支援将測試結果導出為CSV、JSON、Markdown等格式,友善進一步分析和比較。
4. 高度可配置:BenchmarkDotNet提供了豐富的配置選項,可以根據需求對測試進行精細調整。使用者可以設定測試運作次數、疊代次數、預熱次數等參數,以及啟用禁用不同的分析器和報告器。
5. 跨平台支援: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):最基本的基準測試類型,用于測試一段代碼在一次疊代中的執行時間。
- 操作基準測試(OperationBenchmark):在指定時間内重複執行某個操作,并計算每個操作的執行時間。
- 參數化基準測試(ParamBenchmark):用于測試在不同參數或者資料集下的執行時間,可以通過 Attributes 來指定參數。
- 微基準測試(Microbenchmark):專門用于測試微小的代碼片段,如通路一個數組元素的速度等。
在實際測試中,開發者根據自己的需求和測試場景選擇不同的測試類型,并通過 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。
- Affinity:将線程綁定到特定的 CPU 核心上,可選值為 None、All、Even 或 Odd。預設值為 None。
- Jit:指定編譯器的版本,可選值為 LegacyJit、RyuJit 或 Auto。預設值為 Auto。
- Platform:指定基準測試所在程序的 CPU 架構,可選值為 AnyCpu、X64 或 X86。預設值為 AnyCpu。
- Runtime:指定基準測試所使用的運作時平台,可選值為 Core、Clr 或 Mono。預設值為 Core。
- TargetFrameworkMoniker:指定基準測試所使用的 .NET Framework 版本,例如 .NET Framework 4.5、.NET Core 3.1 等。
- BaselineSwitch:指定一個指令行開關,用于訓示基準測試是否作為一個基準行測試來運作。預設值為 false。
- EnvironmentVariables:包含要傳遞給基準測試程序的環境變量字典。
- Categories:指定分類清單,以便在基準測試報告中對測試進行分組。
在類上使用 [SimpleJob] 特性進行标記,并指定相應的測試類型:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
[SimpleJob(RuntimeMoniker.NetCoreApp50, baseline: true)]
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
[SimpleJob(RuntimeMoniker.Net472)]
public class MyBenchmark
{
// test methods
}
輸出格式
BenchmarkDotNet 支援多種輸出格式,包括以下幾種:
- Brief:輸出簡潔的摘要資訊,包括測試名稱、平均值、标準差等統計資料。
- Default:輸出詳細的測試結果,包括測試名稱、測試方法、平均值、标準差等統計資料、原始測試資料、吞吐量和分布圖等。
- 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 支援多種自定義參數,包括以下幾種:
- Job:指定運作測試的環境和條件,如運作時版本、平台、垃圾回收器等。
- IterationCount:指定每個測試的疊代次數,以便獲得更精确的資料點和穩定的統計資料。
- WarmupCount:指定每個測試的預熱次數,以便使 JIT 編譯器預熱運作時環境。
- LaunchCount:指定每個測試的啟動次數,以便消除瞬時啟動時間的影響。
- Accuracy:指定測試結果的準确性和精度。
- Baseline:指定基準測試方法,以便作為比較對象。
- Order:指定測試方法的執行順序。
可以在類上使用 [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 對測試結果進行自動分析,生成多種統計資料和可視化效果,包括以下幾種:
- Mean:平均值,表示總體的中心趨勢水準。
- StdDev:标準差,表示總體的離散程度和穩定性。
- Median:中位數,表示排序後的中間值。
- Q1/Q3:第一/三四分位數,表示排序後的上/下四分之一位置的值。
- Max/Min:最大/最小值,表示排序後的極端值。
- Percentiles:百分位數,表示排序後的特定位置的值。
- Histogram:直方圖,表示測試結果的頻率分布情況。
- Boxplot:箱線圖,表示測試結果的五項摘要統計資料和異常值。
- Summary:摘要資訊,表示測試結果的主要統計資料和可信區間。
可以在運作測試後檢視控制台輸出和生成的報告檔案,以便了解測試結果的詳細資訊和分析結果。
實戰案例
以下是一個使用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`。在這兩個方法中,我們分别實作了冒泡排序和快速排序的算法。
最後,在`Main`方法中,我們使用`BenchmarkRunner.Run`方法來運作基準測試,并生成性能分析報告。
運作上述代碼後,BenchmarkDotNet将自動運作冒泡排序和快速排序的測試方法,并生成包含性能分析報告的輸出。可以根據需要調整數組規模和其他配置參數,以擷取更詳細的性能分析結果。
另外在輸出目錄下,BenchmarkDotnet 會輸出性能測試結果檔案:
打開 html 版本後看到的跟剛才控制台的是一樣的
以上是 BenchmarkDotNet 的基本使用方法和功能。BenchmarkDotNet 有着豐富的 API 和調整參數的選項,可以進行進階性能分析和可視化效果。它可以幫助開發人員優化和改進代碼,并提升應用程式的性能和穩定性。