|
|
|
|
|
BenchmarkDotNet可幫助你將方法轉(zhuǎn)化為基準、跟蹤其性能并共享可重現(xiàn)的測量實驗。這并不比編寫單元測試難!在引擎蓋下,它執(zhí)行了很多保證可靠和精確結(jié)果的技能。BenchmarkDotNet可以保護你免受常見的基準測試錯誤的影響,并在你的基準設計或獲得的測量結(jié)果出現(xiàn)問題時向你發(fā)出警告。結(jié)果以用戶友好的形式呈現(xiàn),突出顯示有關實驗的所有重要事實。該庫被包括 .NET Runtime 在內(nèi)的14300 多個項目采用,并得到 .NET Foundation 的支持。
開始編寫基準測試很容易,查看示例:
[SimpleJob(RuntimeMoniker.Net472, baseline: true)]
[SimpleJob(RuntimeMoniker.NetCoreApp30)]
[SimpleJob(RuntimeMoniker.NativeAot70)]
[SimpleJob(RuntimeMoniker.Mono)]
[RPlotExporter]
public class Md5VsSha256
{
private SHA256 sha256 = SHA256.Create();
private MD5 md5 = MD5.Create();
private byte[] data;
[Params(1000, 10000)]
public int N;
[GlobalSetup]
public void Setup()
{
data = new byte[N];
new Random(42).NextBytes(data);
}
[Benchmark]
public byte[] Sha256() => sha256.ComputeHash(data);
[Benchmark]
public byte[] Md5() => md5.ComputeHash(data);
}
BenchmarkDotNet 自動在所有運行時運行基準測試,匯總測量結(jié)果,并打印包含最重要信息的匯總表:
BenchmarkDotNet=v0.12.0, OS=Windows 10.0.17763.805 (1809/October2018Update/Redstone5)
Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
[Host] : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT
Net472 : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT
NetCoreApp30 : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT
NativeAot70 : .NET 7.0.0-preview.4.22172.7, X64 NativeAOT
Mono : Mono 6.4.0 (Visual Studio), X64
| Method | Runtime | N | Mean | Error | StdDev | Ratio |
|------- |-------------- |------ |-----------:|----------:|----------:|------:|
| Sha256 | .NET 4.7.2 | 1000 | 7.735 us | 0.1913 us | 0.4034 us | 1.00 |
| Sha256 | .NET Core 3.0 | 1000 | 3.989 us | 0.0796 us | 0.0745 us | 0.50 |
| Sha256 | NativeAOT 7.0 | 1000 | 4.091 us | 0.0811 us | 0.1562 us | 0.53 |
| Sha256 | Mono | 1000 | 13.117 us | 0.2485 us | 0.5019 us | 1.70 |
| | | | | | | |
| Md5 | .NET 4.7.2 | 1000 | 2.872 us | 0.0552 us | 0.0737 us | 1.00 |
| Md5 | .NET Core 3.0 | 1000 | 1.848 us | 0.0348 us | 0.0326 us | 0.64 |
| Md5 | NativeAOT 7.0 | 1000 | 1.817 us | 0.0359 us | 0.0427 us | 0.63 |
| Md5 | Mono | 1000 | 3.574 us | 0.0678 us | 0.0753 us | 1.24 |
| | | | | | | |
| Sha256 | .NET 4.7.2 | 10000 | 74.509 us | 1.5787 us | 4.6052 us | 1.00 |
| Sha256 | .NET Core 3.0 | 10000 | 36.049 us | 0.7151 us | 1.0025 us | 0.49 |
| Sha256 | NativeAOT 7.0 | 10000 | 36.253 us | 0.7076 us | 0.7571 us | 0.49 |
| Sha256 | Mono | 10000 | 116.350 us | 2.2555 us | 3.0110 us | 1.58 |
| | | | | | | |
| Md5 | .NET 4.7.2 | 10000 | 17.308 us | 0.3361 us | 0.4250 us | 1.00 |
| Md5 | .NET Core 3.0 | 10000 | 15.726 us | 0.2064 us | 0.1930 us | 0.90 |
| Md5 | NativeAOT 7.0 | 10000 | 15.627 us | 0.2631 us | 0.2461 us | 0.89 |
| Md5 | Mono | 10000 | 30.205 us | 0.5868 us | 0.6522 us | 1.74 |
測量數(shù)據(jù)可以導出為不同格式(md、html、csv、xml、json 等),包括繪圖:
支持的運行時: .NET 5+、.NET Framework 4.6.1+、.NET Core 2.0+、Mono、NativeAOT
支持的語言: C#、F#、Visual Basic
支持的操作系統(tǒng): Windows、Linux、macOS
支持的架構(gòu): x86、x64、ARM , ARM64, Wasm 和 LoongArch64
特征
BenchmarkDotNet 具有大量在綜合性能調(diào)查中必不可少的功能。四個方面定義了這些功能的設計: 簡單性、自動化、可靠性和友好性。
簡單
如果你想編寫基準測試,而你不是一位經(jīng)驗豐富的性能工程師,你可以使用簡單的 API 以聲明式的方式設計非常復雜的性能實驗。
例如,如果你想?yún)?shù)化你的基準,標記一個字段或一個屬性[Params(1, 2, 3)]
:BenchmarkDotNet 將枚舉所有指定的值并為每個案例運行基準。如果你想相互比較基準,請通過[Benchmark(Baseline = true)]
將其中一個基準標記為基準:BenchmarkDotNet
會將其與所有其他基準進行比較。如果要比較不同環(huán)境中的性能,請使用jobs。例如,你可以通過 [SimpleJob(RuntimeMoniker.NetCoreApp30)]
和[SimpleJob(RuntimeMoniker.Mono)]
在 .NET Core 3.0 和 Mono 上運行所有基準測試。
如果你不喜歡屬性,你可以通過 fluent 風格調(diào)用大部分 API,并編寫如下代碼:
ManualConfig.CreateEmpty() // A configuration for our benchmarks
.AddJob(Job.Default // Adding first job
.WithRuntime(ClrRuntime.Net472) // .NET Framework 4.7.2
.WithPlatform(Platform.X64) // Run as x64 application
.WithJit(Jit.LegacyJit) // Use LegacyJIT instead of the default RyuJIT
.WithGcServer(true) // Use Server GC
).AddJob(Job.Default // Adding second job
.AsBaseline() // It will be marked as baseline
.WithEnvironmentVariable("Key", "Value") // Setting an environment variable
.WithWarmupCount(0) // Disable warm-up stage
);
如果你更喜歡命令行體驗,則可以通過任何控制臺應用程序中的控制臺參數(shù)配置基準測試 (不支持其他類型的應用程序)。
自動化
可靠的基準測試總是包含大量樣板代碼。
讓我們考慮一下在典型情況下你應該做什么。首先,你應該執(zhí)行試點實驗并確定最佳的方法調(diào)用次數(shù)。接下來,你應該執(zhí)行幾次預熱迭代并確保你的基準測試達到穩(wěn)定狀態(tài)。之后,你應該執(zhí)行主要迭代并計算一些基本統(tǒng)計數(shù)據(jù)。如果你在基準測試中計算了一些值,你應該以某種方式使用它來防止死代碼消除。如果你使用循環(huán),你應該關心循環(huán)展開對結(jié)果的影響(這可能取決于處理器架構(gòu))。獲得結(jié)果后,你應該檢查所獲得的性能分布的一些特殊屬性,例如多模態(tài)或極高的離群值。你還應該評估基礎設施的開銷,并從結(jié)果中扣除。
如果你從頭開始編寫此代碼,很容易出錯并破壞你的測量結(jié)果。請注意,這是你在基準測試期間應遵循的完整清單的簡化版本:還有許多其他隱藏的陷阱需要妥善處理。幸運的是,你不必擔心,因為 BenchmarkDotNet會為你完成這些無聊且耗時的工作。
此外,庫可以幫助你完成一些你可能希望在調(diào)查期間執(zhí)行的高級任務。例如,BenchmarkDotNet 可以測量托管和本機內(nèi)存流量并為你的基準打印反匯編列表。
可靠性
許多手寫的基準測試會產(chǎn)生錯誤的數(shù)字,從而導致錯誤的業(yè)務決策。BenchmarkDotNet 保護你免受大多數(shù)基準測試陷阱的影響,并允許實現(xiàn)高測量精度。
你不應該擔心方法調(diào)用的完美次數(shù)、預熱次數(shù)和實際迭代次數(shù):BenchmarkDotNet 嘗試選擇最佳基準測試參數(shù),并在測量預測和所有基準測試運行的總持續(xù)時間之間取得良好的權(quán)衡. 所以,你不應該使用任何幻數(shù)(比如“我們應該在這里執(zhí)行 100 次迭代”),庫會根據(jù)統(tǒng)計指標的值為你做這件事。
BenchmarkDotNet 還阻止對使用 DEBUG 模式構(gòu)建的未優(yōu)化程序集進行基準測試,因為相應的結(jié)果將不可靠。如果你有一個附加的調(diào)試器,如果你使用管理程序(HyperV,VMware,VirtualBox),或者如果你對當前環(huán)境有任何其他問題,它會打印一條警告。
在 6 年多的開發(fā)過程中,我們遇到了許多可能會破壞你的測量結(jié)果的不同問題。在 BenchmarkDotNet 內(nèi)部,有很多啟發(fā)式、檢查、技巧和技巧可以幫助你提高結(jié)果的可靠性。
友好
性能數(shù)據(jù)分析是一項耗時的活動,需要注意力、知識和經(jīng)驗。BenchmarkDotNet 為你執(zhí)行此分析的主要部分,并以用戶友好的形式呈現(xiàn)結(jié)果。
實驗結(jié)束后,你會得到一個匯總表,其中包含有關已執(zhí)行基準測試的大量有用數(shù)據(jù)。默認情況下,它只包含最重要的列,但可以輕松自定義。列集是自適應的,取決于基準定義和測量值。例如,如果你將其中一個基準標記為基線,你將獲得額外的列,這些列將幫助你將所有基準與基線進行比較。默認情況下,它始終顯示均值列,但如果我們檢測到均值和中值之間存在巨大差異,則會顯示兩列。
BenchmarkDotNet 試圖找到性能分布的一些不尋常屬性并打印有關它的好消息。例如,它會在多峰分布或高異常值的情況下向你發(fā)出警告。在這種情況下,你可以向上滾動結(jié)果并查看每個分布的 ASCII 樣式直方圖,或使用生成漂亮的 png 圖。
BenchmarkDotNet 不會讓你超載數(shù)據(jù);它僅根據(jù)你的結(jié)果顯示基本信息:它允許你為原始案例保留小的摘要,并僅為復雜案例擴展它。當然,你可以手動請求任何其他統(tǒng)計數(shù)據(jù)和可視化。如果你不自定義摘要視圖,則默認演示文稿將盡可能方便用戶使用。:)
誰使用 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 , Expecto , ImageSharp , RavenDB , NodaTime、 Jint、 NServiceBus、 Serilog 、Autofac、 Npgsql、 Avalonia、 ReactiveUI、 SharpZipLib、 LiteDB 、 GraphQL for .NET、 .NET Docs、 RestSharp、 MediatR、 TensorFlow.NET、 Apache Thrift。 在 GitHub 上,你可以找到 12600 多個問題、5200 多個提交和 1,600,000 多個 涉及 BenchmarkDotNet 的文件。
了解有關基準測試的更多信息
BenchmarkDotNet 并不是神奇地使你的所有基準測試正確并為你分析測量結(jié)果的靈丹妙藥。即使你使用這個庫,你仍然應該知道如何設計基準實驗以及如何根據(jù)原始數(shù)據(jù)做出正確的結(jié)論。如果你想了解更多關于基準測試方法和良好實踐的信息,建議閱讀 Andrey Akinshin(BenchmarkDotNet 項目負責人)所著的一本書:“Pro .NET Benchmarking”。使用這個深入的指南來正確設計基準、測量 .NET 應用程序的關鍵性能指標并分析結(jié)果。本書介紹了數(shù)十個案例研究,可幫助你理解復雜的基準測試主題。你將避免常見的陷阱,控制測量的準確性。
構(gòu)建狀態(tài)
搭建服務器 | 平臺 | 構(gòu)建狀態(tài) |
---|---|---|
Azure Pipelines | 視窗 | |
Azure Pipelines | Ubuntu | |
Azure Pipelines | 蘋果系統(tǒng) | |
AppVeyor | 視窗 | |
GitHub 操作 | * |
歡迎投稿!
BenchmarkDotNet 已經(jīng)是一個穩(wěn)定的全功能庫,可以在專業(yè)水平上進行性能調(diào)查。而且還在不斷進化!我們一直在添加新功能,但我們有太多新奇的想法。任何幫助將不勝感激。你可以開發(fā)新功能、修復錯誤、改進文檔或做一些其他很酷的事情。
如果你想做出貢獻,請查看貢獻指南和待售問題。如果你有新想法或想抱怨錯誤,請隨時創(chuàng)建一個新問題。讓我們一起構(gòu)建最好的基準測試工具!
行為守則
該項目采用了貢獻者公約定義的行為準則 ,以闡明我們社區(qū)的預期行為。有關詳細信息,請參閱 .NET Foundation 行為準則。