我有单元测试。如果其中之一失败,我的构建就会失败。
我想将相同的原则应用于性能。我有一系列针对通过库的几个热路径的微基准测试。根据经验,这些领域的放缓对图书馆的整体性能产生了不成比例的影响。
如果有某种方法可以有一些“性能构建”的概念,如果性能回归太显着,它可能会失败,那就太好了。
我曾考虑过不得超过的硬编码阈值。就像是:
Assert.IsTrue(hotPathTestResult.TotalTime <= threshold)
但是将其与绝对值挂钩是硬件和环境相关的,因此很脆弱。
有没有人实现过这样的东西?微软为 Kestrel 做了什么?
我使用以下方法实现了以下基准BenchmarkDotNet:
public class ForVsFillVsEnumerable
{
private bool[] data;
[Params(10, 100, 1000)]
public int N;
[GlobalSetup]
public void Setup()
{
data = new bool[N];
}
[Benchmark]
public void Fill()
{
Array.Fill(data, true);
}
[Benchmark]
public void For()
{
for (int i = 0; i < data.Length; i++)
{
data[i] = true;
}
}
[Benchmark]
public void EnumerableRepeat()
{
data = Enumerable.Repeat(true, N).ToArray();
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17763.195 (1809/October2018Update/Redstone5)
Intel Core i7-8700K CPU 3.70GHz (Coffee Lake), 1 CPU, 12 …Run Code Online (Sandbox Code Playgroud) 假设您正在编写一些与 BenchmarkDotNet 一起使用的基准测试,这些基准测试多目标为net48和net6.0,并且这些基准测试之一只能针对该net6.0目标进行编译。
显而易见的事情是使用类似的方法从构建中排除该特定基准net48:
#if NET6_0_OR_GREATER
[Benchmark]
public void UsingSpan()
{
using var stream = new MemoryStream();
writeUsingSpan(stream, _array);
}
static void writeUsingSpan(Stream output, double[] array)
{
var span = array.AsSpan();
var bytes = MemoryMarshal.AsBytes(span);
output.Write(bytes);
}
#endif // NET6_0_OR_GREATER
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不起作用,并且它不起作用的方式取决于TargetFrameworks项目文件中的属性中指定的目标的顺序。
如果您订购框架,那么net6.0首先<TargetFrameworks>net6.0;net48</TargetFrameworks>(在上面的示例中)该UsingSpan()方法将包含在两个目标中,导致目标net48和输出出现 BenchmarkDotNet 构建错误,如下所示:
| Method | Job | Runtime | Mean | Error | StdDev |
|------------------ |------------------- |------------------- |-----------:|----------:|----------:|
| …Run Code Online (Sandbox Code Playgroud) 我想在我现在正在使用的一些遗留代码上使用 BenchmarkDotNet。它是用 C# Net462 编写的。这是一个庞大、古老且复杂的系统,我想对某些特定类中的一些方法进行基准测试。这些类使用依赖注入,我不确定如何做到这一点。到目前为止我看到的所有示例都没有使用任何依赖注入。
有人有什么想法或例子我可以看一下吗?
非常感谢。
我正在尝试使用 BenchmarkDotNet 为库准备性能回归测试。这要求我将相同的测试与旧(稳定)版本的库进行比较。现在,可以选择为作业提供不同版本的 NuGet 包。似乎没有一个选项可以代替引用不同的程序集。
我尝试过自定义构建配置:
<ItemGroup Condition="'$(Configuration)' == 'Baseline'">
<Reference Include="MyAssembly">
<HintPath>lib\baseline\MyAssembly.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' != 'Baseline'">
<Reference Include="MyAssembly">
<HintPath>lib\current\MyAssembly.dll</HintPath>
</Reference>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
但是当尝试通过 BenchmarkDotNet 使用这些配置时
public static void Main(string[] args) {
var summary = BenchmarkRunner.Run(typeof(Program).Assembly,
DefaultConfig.Instance
.With(Job.Default.WithCustomBuildConfiguration("Baseline"))
.With(Job.Default.WithCustomBuildConfiguration("Current")));
}
Run Code Online (Sandbox Code Playgroud)
我收到构建错误,表明该程序集根本没有被引用。BenchmarkDotNet 还有助于清除它创建的任何临时工件,因此我什至无法查看生成的项目文件来弄清楚它的外观。
这里唯一的解决方法是将库包装在 NuGet 包中吗?或者在(对于这种情况看似稀疏的)文档中是否有我忽略的东西?
这个问题似乎与我遇到的构建错误隐约相关。
我正在使用 BenchmarkDotNet 及其 MemoryDiagnoser 功能。
考虑以下基准:
[Benchmark]
public void Dummy()
{
var buffer = new byte[1];
}
Run Code Online (Sandbox Code Playgroud)
我希望它恰好分配 1 个字节。
但是基准测试结果显示总共分配了 32 个字节。怎么来的?我觉得这很有误导性。
| Method | Mean | Error | StdDev | Median | Ratio | Rank | Gen 0 | Gen 1 | Gen 2 | Allocated |
|------- |---------:|----------:|----------:|---------:|------:|-----:|-------:|------:|------:|----------:|
| Dummy | 4.486 ns | 0.1762 ns | 0.5196 ns | 4.650 ns | 1.00 | 1 | 0.0038 | - | - | 32 B |
why …Run Code Online (Sandbox Code Playgroud) 介绍
我们正试图捕获潜在的内存泄漏BenchmarksDotNet.
为了简单的例子,这里是一个简单的TestClass:
public class TestClass
{
private readonly string _eventName;
public TestClass(string eventName)
{
_eventName = eventName;
}
public void TestMethod() =>
Console.Write($@"{_eventName} ");
}
Run Code Online (Sandbox Code Playgroud)
我们正在通过NUnit测试实现基准测试netcoreapp2.0:
[TestFixture]
[MemoryDiagnoser]
public class TestBenchmarks
{
[Test]
public void RunTestBenchmarks() =>
BenchmarkRunner.Run<TestBenchmarks>(new BenchmarksConfig());
[Benchmark]
public void TestBenchmark1() =>
CreateTestClass("Test");
private void CreateTestClass(string eventName)
{
var testClass = new TestClass(eventName);
testClass.TestMethod();
}
}
Run Code Online (Sandbox Code Playgroud)
测试输出包含以下摘要:
Method | Mean | Error | Allocated |
--------------- |-----:|------:|----------:|
TestBenchmark1 | NA | …Run Code Online (Sandbox Code Playgroud) 我想使用 BenchmarkDotNet 库测量控制台应用程序中某些方法的性能。
问题是:我应该在解决方案中创建一个单独的项目,在其中复制我感兴趣的测量方法并在那里进行测量,还是应该将测量所需的所有属性添加到现有项目中?
这里的约定是什么?
我已将“构建”设置为“发布”模式。
我正在运行我的.NET Core 3.1控制台应用程序Benchmark DotNet。但它告诉我,
摘要 -> 基准测试是使用附加的调试器执行的
如何在构建模式下完全关闭调试器Release?
我在 BenchmarkDotNet 上遇到问题,很难解决
这是我的项目结构:
-
| - Infrastructure
| |
| | - TestsBenchmark
| | - MyInfra.sln
| - src
| - Tests
| - MyProduct.sln
Run Code Online (Sandbox Code Playgroud)
TestsBenchmark引用Tests并且只有这行代码:
BenchmarkSwitcher.FromAssembly(typeof(BasicTests).Assembly).RunAll();
Run Code Online (Sandbox Code Playgroud)
但是当我通过它运行dotnet run -c Release它时它会抛出
// Generate Exception: Unable to find Tests in ...\Infrastructure and its subfolders. Most probably the name of output exe is different than the name of the .(c/f)sproj
以前我的项目结构是这样的:
-
| - src
| - Tests
| - TestsBenchmark
Run Code Online (Sandbox Code Playgroud)
一切正常
复制步骤(手动),它重新创建文件夹结构、项目、项目关系、解决方案并添加 nuget。在某个空文件夹中的例如 powershell …
benchmarkdotnet ×10
c# ×5
.net ×2
.net-4.6 ×1
arrays ×1
autofac ×1
memory ×1
memory-leaks ×1
performance ×1
tinyioc ×1