基準測試工具 --- BenchmarkDotNet

2023-07-21 15:01:23

介紹

今天介紹一個非常強大的基於.Net 的基準測試工具BenchmarkDotNet

BenchmarkDotNet 已經被14300多個專案採用,包括非常多的知名開源專案,例如

  • dotnet/performance(.Net所有執行時的基準測試專案)
  • dotnet/runtime(.Net 執行時庫),
  • Roslyn (c#和Visual Basic編譯器),
  • Mono、 ASP.NET Core、 ML.NET、 Entity Framework Core、 PowerShell SignalR、 f#、 Orleans, Newtonsoft.Json、Elasticsearch.Net、Dapper等諸多知名開源專案。

BenchmarkDotNet能夠自動在所有執行時執行基準,彙總測試結果,並列印一個彙總表,其中包含眾多基準資訊:

這些測試資料也可以匯出為不同的格式(md, html, csv, xml, json等),包括圖片:

最主要的是它可以非常容易的編寫基準測試,只需要安裝好NuGet包之後,給需要測試的方法標註 Attribute,就可以執行測試。

Demo

這裡可以使用控制檯或單元測試來進行測試。

官方GitHub上分別提供了基於控制檯和基於XUnit單元測試的基準測試:

接下來,以一個基於控制檯的基準測試來講解一下:

class Program
{
    static void Main(string[] args)
    {
        BenchmarkRunner.Run<BenchmarkTest>();
    }
}

[SimpleJob(RunStrategy.ColdStart, iterationCount: 100000)]
public class BenchmarkTest
{
    [Benchmark()]
    public void CreateTuple()
    {
        var temp = new Tuple<int, string>(1, "");
    }
}

上述程式碼中,建立了一個 BenchmarkTest 類用於做基準測試,然後建立了一個 CreateTuple()方法,該方法建立一個 Tuple 物件,然後我們給這個方法標記 [Benchmark()] ,標記該方法用於做基準測試,然後在BenchmarkTest 類上標記 [SimpleJob(RunStrategy.ColdStart, iterationCount: 100000)],表示是以冷啟動的方式,執行該類要測試的基準方法100000次。

接下來,來看一下測試結果,輸出:

講解

可以看到控制檯輸出分為了幾個部分。

Summary

可以看到控制檯輸出中黃色部分加下方表格,就是該報告主要內容,能看到當前執行測試時的執行環境,測試條件(IterationCount=100000 RunStrategy=ColdStart),表格中也能看到具體效能,比如,

  1. Method(測試方法的名稱為CreateTuple)。
  2. Mean(測試執行的平均時間為420.7納秒)。
  3. Error(測試執行的標準誤差為16.96納秒)。
  4. StdDev(所有測試執行的標準偏差為1630納秒)。
  5. Median(所有測試執行的中位數為300納秒)。

Legends

簡單描述了表格中的一些引數。

實際上在 BenchmarkDotNet 中,這樣的統計資料列大概有90多條,可以參考這裡(https://github.com/dotnet/BenchmarkDotNet/blob/master/src/BenchmarkDotNet/Columns/Column.cs)

下面挑出一些常用統計列,簡單解釋:

  • Method: 測試方法的名稱。
  • Mean: 所有測試執行的平均時間。
  • Error: 測試執行的標準誤差,標準誤差是測試結果的離散程度的度量,標準誤差越小,表示測試結果越穩定。
  • StdDev: 所有測試執行的標準偏差,標準偏差是測試結果的離散程度的度量,標準偏差越小,表示測試結果越接近平均值。
  • Median: 所有測試執行的中位數。中位數是測試結果的中間值,如果測試結果的個數為奇數,則中位數為中間的那個值;如果測試結果的個數為偶數,則中位數為中間兩個值的平均值。
  • Ratio: 每個測試執行的平均時間與基準測試執行的平均時間的比值。基準測試是效能最好的測試,它的比值為 1.0。其他測試的比值表示它們相對於基準測試的效能表現,比值越小,表示效能越好。
  • RatioSD: 所有測試執行的比值的標準偏差。標準偏差越小,表示比值的離散程度越小,測試結果更穩定。
  • Gen 0: 所有測試執行期間生成的第 0 代垃圾回收的次數。垃圾回收是 .NET 執行時自動回收不再使用的記憶體的機制,Generational Garbage Collection 是 .NET 中的一種垃圾回收演演算法。
  • Gen 1: 所有測試執行期間生成的第 1 代垃圾回收的次數。
  • Gen 2: 所有測試執行期間生成的第 2 代垃圾回收的次數。
  • Allocated: 所有測試執行期間分配的記憶體總量。

Warings

會給出一些警告,或者建議操作,像範例程式碼中生成100000個 Tuple 物件,他就報警方法執行實現太短,建議使用更多操作將其增加到至少100.0000 ms。

Export

上面其實還有一部分控制檯內容是 Export 內容 ,如下圖所示:

預設給你生成了三種格式的報告,CSV格式,Markdownn格式,和Html格式,生成路徑是執行根目錄下的BenchmarkDotNet.Artifacts\results\資料夾下的 BenchmarkDotNet.Console.BenchmarkTest-report檔案。

總結

本篇拋磚引玉,只講述基於控制檯做基準測試,強烈建議各位看官閱讀Github上的範例,學會使用更多的引數,藉助 BenchmarkDotNet 做出更準確準確、更可靠的效能測試結果。

參考

BenchmarkDotNet Github地址:https://github.com/dotnet/BenchmarkDotNet

基於控制檯Demo Github地址:https://github.com/dotnet/BenchmarkDotNet/tree/master/samples/BenchmarkDotNet.Samples

基於Xunit單元測試Demo Github地址:https://github.com/dotnet/BenchmarkDotNet/tree/master/tests/BenchmarkDotNet.IntegrationTests

統計資料列參考 Githu地址:https://github.com/dotnet/BenchmarkDotNet/blob/master/src/BenchmarkDotNet/Columns/Column.cs