项目背景

   BenchmarkDotNet帮助您把程序方法的执行过程转换为基准测试数据,并跟踪其性能,使得测数量数据可以共享和重复。 这并不比写单元测试复杂!基于这个引擎,它执行了一系列精妙的算法,保证了测试数据的可靠性和准确性。BenchmarkDotNet让你远离常见的基准测试错误,并在基准测试设计或获得的度量出现问题时发出警告。基准测试结果会以用户友好的形式呈现出来,实验的重要数据会高亮展示。 该库被3500多个项目(包括.NET Core)采用,并由 .NET基金会提供支持。

  很容易开始编写基准测试,请查看一个示例( 此处是可复制的可粘贴版本):

    [SimpleJob(RuntimeMoniker.Net472, baseline: true)] [SimpleJob(RuntimeMoniker.NetCoreApp30)] [SimpleJob(RuntimeMoniker.CoreRt30)] [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自动在所有运行时上运行基准测试,聚合度量值,并打印包含最重要信息的摘要表:

    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 CoreRt30 : .NET CoreRT 1.0.28231.02
    @Commit:741d61493c560ba96e8151f9e56876d4d3828489, X64 AOT 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 | CoreRt 3.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 | CoreRt 3.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 | CoreRt 3.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 | CoreRt 3.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 |

  测量数据可以导出为不同的格式(md、html、csv、xml、json等),包括绘图:

支持 运行时:.NET Framework 4.6.1+, .NET Core 2.0+, Mono, CoreRT
支持 语言:C#, F#, Visual Basic
支持 操作系统:Windows, Linux, macOS

特性

  BenchmarkDotNet有许多在全面的性能调查中是必不可少的特性。四个方面定义了这些特性的设计: 简单, 自动化, 可靠性, 和 友好性.

简单

  即便你不是一个经验丰富的性能测试工程师,你依然可以使用简单的api以声明式风格设计非常复杂的性能实验。

  例如,如果要 参数化基准,请使用[Params(1,2,3)]标记字段或属性:BenchmarkDotNet将枚举所有指定的值,并为每种情况运行基准。

  如果你想对比不同的基准,可以通过标记[benchmark(baseline:true)]将其中一个基准标记为 基准:BenchmarkDotNet将其与所有其他基准进行比较。

[SimpleJob(RuntimeMoniker.NetCoreApp30)]and [SimpleJob(RuntimeMoniker.Mono)]. 例如,你可以通过标记 [SimpleJob(RuntimeMoniker.NetCoreApp30)][SimpleJob(RuntimeMoniker.Mono)]来让程序运行在.NET Core 3.0 and Mono 环境.

  如果你不喜欢用属性标注的方式,你可以通过调用Fluent API,比如这种写法:

    ManualConfig.CreateEmpty() // A configuration for our benchmarks .With(Job.Default // Adding first job .With(ClrRuntime.Net472) // .NET Framework 4.7.2 .With(Platform.X64) // Run as x64 application .With(Jit.LegacyJit) // Use LegacyJIT instead of the default RyuJIT .WithGcServer(true) // Use Server GC ).With(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 );

  如果你喜欢命令行,你可以在控制台程序或者 .NET Core命令行工具中使用 控制台参数来执行dll的基准测试:

    dotnet benchmark MyAssembly.dll --runtimes net472 netcoreapp2.1 Mono

自动化

  可靠的基准测试总是包含许多样例代码。

  让我们想想在一个典型的案例中你应该做什么。首先,您应该做一个试验性实验,并确定方法调用的最佳数量。接下来,您应该执行几个预热迭代,并确保您的基准达到稳定状态。 之后,您应该执行主迭代并计算一些基本统计信息。如果在基准测试中计算一些值,应该以某种方式使用它来防止“死代码消除”——永远不可能被执行到的代码。如果使用循环,则应注意循环展开对结果的影响(这可能取决于处理器体系结构)。 一旦得到结果,就应该检查所获得的性能分布的一些特殊属性像多模态或极高的异常值。 你也要评估基础设施的损耗,并将它们从你结果中剔除。如果要测试多个环境,则应在每个环境中执行测量并手动聚合结果。

  如果你完全从头自己写基准测试代码,非常容易犯错并影响您的测试结果。值得注意的是,这是完整检查表的简短版本,在基准测试期间应遵循:还有很多隐藏的陷阱需要妥善处理。幸运的是,你不必担心因为BenchmarkDotNet已经帮你把无聊而耗时的事情给做了。[how-it-works](https://BenchmarkDotNet.org/articles/guides/how-it-works.html).

  此外,该库还可以帮助您完成一些高级任务,您可能希望在调查期间执行这些任务。 例如,BenchmarkDotNet可以测量 托管https://benchmarkdotnet.org/articles/configs/diagnosers.html#usage和[本机](https://benchmarkdotnet.org/articles/samples/IntroNativeMemory.html内存流量,并打印基准的反汇编列表。

可靠性

  许多手工编写的基准产生错误的数字,导致错误的业务决策。BenchmarkDotNet让您远离大多数基准测试陷阱的影响,并带给您实现高精度的测量结果。您不必担心程序方法调用的最佳、预热和实际迭代的次数:BenchmarkDotNet会选择最佳的基准参数并在度量预测和所有基准运行的总持续时间之间实现良好的权衡。所以,你不需要使用任何魔法数字(比如“我们应该在这里执行100次迭代”),类库将根据统计度量值为您执行此操作。

  BenchmarkDotNet还防止对使用调试模式生成的未优化程序集进行基准测试,因为相应的结果是不可靠的。如果使用hypervisor(HyperV、VMware、VirtualBox),附加的调试器,或者如果你对当前的环境有任何其他问题,它会打印一个警告。

  在6年多的发展过程中,我们遇到过很多对测量结造成干扰的问题。在BenchmarkDotNet中,有大量的推断,检测,黑科技和技巧来帮助您提高测试的稳定性。

友好

  性能数据分析是一项耗时的工作,需要专注、知识和经验。BenchmarkDotNet为您完成数据分析的主要部分,并以用户友好的形式显示结果。

  实验结束后,您将得到一个概览表,其中包含有关已执行基准的许多有用数据。 默认地,概览表只包含了最重要的字段, 但是他们可以 容易地定制. 列头字段的设置,取决于基准定义和测量值。 比如, 如果你标记了某个基准测试为 基线,那么,你将得到更多的列,它们会帮助你和其它基准测试做比较。默认情况下,它总是显示Mean列,但是如果我们发现平均值和中值之间存在巨大的差异,两列都将展示。

  BenchmarkDotNet试图找到性能分布的一些不寻常的属性,并把与之相关的信息打印出来。例如,当出现多模式分布或高异常值时,它会发出警告。在这种情况下,您可以向上滚动结果并检查每个分布的ASCII样式直方图,或者使用 [RPlotExporter]生成漂亮的图片。

  BenchmarkDotNet不会让数据超载;它只显示根据结果而定的基本信息:它允许您保持原始案例的摘要较小,并且只扩展复杂案例的摘要。当然,您可以手动地请求任何其他统计和可视化。如果你不想自定义结果概览视图,默认的展示方式已经足够友好。:)

谁会使用 BenchmarkDotNet

  每个人!BenchmarkDotNet已经被超过 3500+个项目采用,包括 dotnet/performance(reference benchmarks for all .NET Runtimes), dotnet/runtime(.NET Core runtime and libraries), Roslyn(C# and Visual Basic compiler), Mono, ASP.NET Core, ML.NET, Entity Framework Core, SignalR, F#, Orleans, Newtonsoft.Json, Elasticsearch.Net, Dapper, Expecto, Accord.NET, ImageSharp, RavenDB, NodaTime, Jint, NServiceBus, Serilog, Autofac, Npgsql, Avalonia, ReactiveUI, SharpZipLib, LiteDB, GraphQL for .NET, MediatR, TensorFlow.NET.
在 GitHub上,你可以搜索到与BenchmarkDotNet相关的2500+ issues, 1500+ commits, and 450,000+ files

了解有关基准测试的更多信息

  BenchmarkDotNet不是一个银弹,它神奇地使您的所有基准都正确,并为您分析度量。

  即使你使用这个库,你仍然应该知道如何设计基准实验,以及如何根据原始数据得出正确的结论。 If you want to know more about benchmarking methodology and good practices, it's recommended to read a book by 如果您想了解更多关于基准测试方法和良好实践的信息,建议你读一本Andrey Akinshin (BenchmarkDotNet项目负责人)的书: "Pro .NET Benchmarking"

  使用此深入的指南可以正确地设计基准,测量.NET应用程序的关键性能指标,并分析结果。 这本书提供了几十个案例研究,帮助您理解复杂的基准测试主题。 您将避免常见的陷阱,控制测量的准确性,并提高软件的性能。

版权声明: 本文为智客工坊「楠木大叔」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

results matching ""

    No results matching ""