初次接触BenchmarkDotNet
- 创建控制台程序:
- 引用NuGet包:BenchmarkDotNet,版本:0.13.5
- Program.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
namespace MyBenchmarks
{
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net70)]
[MemoryDiagnoser]
public class TestBooleanArray
{
private bool[] oldBooleanArray;
private bool[] newBooleanArray;
private List<bool> resultBooleanArray;
[Params(800)]
public int N;
[GlobalSetup]
public void Setup()
{
oldBooleanArray = new bool[N];
new BooleanGenerator().NextBoolean(oldBooleanArray);
newBooleanArray = new bool[N];
new BooleanGenerator().NextBoolean(newBooleanArray);
resultBooleanArray = new List<bool>(N);
for (int i = 0; i < oldBooleanArray.Length; i++)
{
//Debug.WriteLine($"oldBooleanArray[{i}]:{oldBooleanArray[i]},newBooleanArray[{i}]:{newBooleanArray[i]},Result:{oldBooleanArray[i] == newBooleanArray[i]}");
//oldBooleanArray[i] == newBooleanArray[i];
resultBooleanArray.Add(false);
}
}
[GlobalCleanup]
public void Cleanup()
{
Console.WriteLine($"Result Count:{resultBooleanArray.Count(t => t == true)}");
}
//[Benchmark(BaseLine=true)]
//public void ComputeMain()
//{
// Compute()
// Console.WriteLine(resultBooleanArray.Count(t => t == true));
//}
[Benchmark]
public void Compute()
{
//resultBooleanArray = new List<bool>(N);
for (int i = 0; i < oldBooleanArray.Length; i++)
{
//Debug.WriteLine($"oldBooleanArray[{i}]:{oldBooleanArray[i]},newBooleanArray[{i}]:{newBooleanArray[i]},Result:{oldBooleanArray[i] == newBooleanArray[i]}");
//oldBooleanArray[i] == newBooleanArray[i];
resultBooleanArray[i] = oldBooleanArray[i] == newBooleanArray[i];
}
//Console.WriteLine(resultBooleanArray.Count(t => t == true));
}
public class BooleanGenerator
{
Random rnd;
public BooleanGenerator()
{
rnd = new Random();
}
public bool NextBoolean()
{
return rnd.Next(0, 2) == 1;
}
public void NextBoolean(bool[] buffer)
{
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = rnd.Next(0, 2) == 1;
}
}
}
}
public class Program
{
public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<TestBooleanArray>();
//Console.ReadKey();
}
}
}
- 实验结果:
// * Summary *
BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.22621.1702/22H2/2022Update/SunValley2)
11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK=7.0.100
[Host] : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2 [AttachedDebugger]
.NET 6.0 : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2
.NET 7.0 : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX2
| Method | Job | Runtime | N | Mean | Error | StdDev |
|-------- |--------- |--------- |---- |---------:|----------:|----------:|
| Compute | .NET 6.0 | .NET 6.0 | 800 | 1.359 us | 0.0272 us | 0.0636 us |
| Compute | .NET 7.0 | .NET 7.0 | 800 | 1.310 us | 0.0267 us | 0.0786 us |
- BenchmarkDotNet代码说明:
- SimpleJob特性:
指定使用测试环境,使用的环境由枚举类 RuntimeMoniker 指定。测试时,可以在同一个类中设置多个SimpleJob,BenchmarkDotNet会根据SimpleJob根据tight的环境测试。注意:没有安装对应的库,测试时,BenchmarkDotNet对应的测试时都是NA。
//使用的NET6.0的环境
[SimpleJob(RuntimeMoniker.Net60)]
//使用NET7.0的环境
[SimpleJob(RuntimeMoniker.Net70)]
public class TestBooleanArray
{
}
- Params特性:
针对属性,赋值参数提供的值。
//BenchmarkDotNet创建类时,N赋值我800
[Params(800)]
public int N;
//BenchmarkDotNet会进行2此测试,分别使用,N=800,N=8000的测试结果。
[Params(800,8000)]
public int N;
针对 [Params(800,8000)] 的测试结果的显示方式:
// * Summary *
BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.22621.1702/22H2/2022Update/SunValley2)
11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK=7.0.100
[Host] : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2 [AttachedDebugger]
.NET 6.0 : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2
.NET 7.0 : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX2
| Method | Job | Runtime | N | Mean | Error | StdDev | Median |
|-------- |--------- |--------- |----- |----------:|----------:|----------:|----------:|
| Compute | .NET 6.0 | .NET 6.0 | 800 | 1.337 us | 0.0258 us | 0.0681 us | 1.349 us |
| Compute | .NET 7.0 | .NET 7.0 | 800 | 1.300 us | 0.0263 us | 0.0775 us | 1.323 us |
| Compute | .NET 6.0 | .NET 6.0 | 8000 | 14.569 us | 0.5402 us | 1.5928 us | 14.721 us |
| Compute | .NET 7.0 | .NET 7.0 | 8000 | 13.357 us | 0.3407 us | 1.0046 us | 13.713 us |
- Benchmark特性:
需要测试的方法上边添加Benchmark特性
[Benchmark]
public void Compute()
{
for (int i = 0; i < oldBooleanArray.Length; i++)
{
resultBooleanArray[i] = oldBooleanArray[i] == newBooleanArray[i];
}
}
- GlobalSetup与GlobalCleanup特性
GlobalSetup特性:类似C#的构造函数,主要针对Benchmark方法中使用的对象进行过初始化。
GlobalCleanup特性:类似C#的析构函数。主要针对Benchmark方法中使用的对象进行过注销。 - MemoryDiagnoser特性
显示测试的方式中,内存的使用情况。一般放在类上边。测试结果中:Allocated字段代表使用的内存的情况:
// * Summary *
BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.22621.1702/22H2/2022Update/SunValley2)
11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK=7.0.100
[Host] : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2 [AttachedDebugger]
.NET 6.0 : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2
.NET 7.0 : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX2
| Method | Job | Runtime | N | Mean | Error | StdDev | Median | Allocated |
|-------- |--------- |--------- |----- |----------:|----------:|----------:|----------:|----------:|
| Compute | .NET 6.0 | .NET 6.0 | 800 | 1.388 us | 0.0278 us | 0.0464 us | 1.391 us | - |
| Compute | .NET 7.0 | .NET 7.0 | 800 | 1.367 us | 0.0265 us | 0.0669 us | 1.363 us | - |
| Compute | .NET 6.0 | .NET 6.0 | 8000 | 14.628 us | 0.5206 us | 1.5351 us | 14.727 us | - |
| Compute | .NET 7.0 | .NET 7.0 | 8000 | 13.212 us | 0.2900 us | 0.8550 us | 13.440 us | - |
以下是Net Framework 4.6、Net Framework 4.8环境的运行结果:
// * Summary *
BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.22621.1702/22H2/2022Update/SunValley2)
11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores
[Host] : .NET Framework 4.8.1 (4.8.9139.0), X86 LegacyJIT [AttachedDebugger]
.NET Framework 4.6.2 : .NET Framework 4.8.1 (4.8.9139.0), X86 LegacyJIT
.NET Framework 4.8.1 : .NET Framework 4.8.1 (4.8.9139.0), X86 LegacyJIT
| Method | Job | Runtime | N | Mean | Error | StdDev | Allocated |
|-------- |--------------------- |--------------------- |----- |----------:|----------:|----------:|----------:|
| Compute | .NET Framework 4.6.2 | .NET Framework 4.6.2 | 800 | 2.444 us | 0.1732 us | 0.5107 us | - |
| Compute | .NET Framework 4.8.1 | .NET Framework 4.8.1 | 800 | 2.409 us | 0.1793 us | 0.5288 us | - |
| Compute | .NET Framework 4.6.2 | .NET Framework 4.6.2 | 8000 | 24.934 us | 1.6724 us | 4.9310 us | - |
| Compute | .NET Framework 4.8.1 | .NET Framework 4.8.1 | 8000 | 24.677 us | 1.7765 us | 5.2381 us | - |
以上代码中测试中,没有内存的消耗。修改Compute方法,增加内存的消耗,代码如下:
[Benchmark]
public void Compute()
{
resultBooleanArray = new List<bool>(N);
for (int i = 0; i < oldBooleanArray.Length; i++)
{
//Debug.WriteLine($"oldBooleanArray[{i}]:{oldBooleanArray[i]},newBooleanArray[{i}]:{newBooleanArray[i]},Result:{oldBooleanArray[i] == newBooleanArray[i]}");
resultBooleanArray.Add(oldBooleanArray[i] == newBooleanArray[i]);
//resultBooleanArray[i] = oldBooleanArray[i] == newBooleanArray[i];
}
//Console.WriteLine(resultBooleanArray.Count(t => t == true));
}
通过以下测试结果可以看出,当N=800时,执行Compute方法时,内存消耗856 B,当N=8000时,执行Compute方法时,内存消耗8056 B。
// * Summary *
BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.22621.1702/22H2/2022Update/SunValley2)
11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK=7.0.100
[Host] : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2 [AttachedDebugger]
.NET 6.0 : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2
.NET 7.0 : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX2
| Method | Job | Runtime | N | Mean | Error | StdDev | Median | Gen0 | Gen1 | Allocated |
|-------- |--------- |--------- |----- |----------:|----------:|----------:|----------:|-------:|-------:|----------:|
| Compute | .NET 6.0 | .NET 6.0 | 800 | 1.982 us | 0.0943 us | 0.2781 us | 2.058 us | 0.1335 | - | 856 B |
| Compute | .NET 7.0 | .NET 7.0 | 800 | 2.113 us | 0.0884 us | 0.2607 us | 2.154 us | 0.1354 | - | 856 B |
| Compute | .NET 6.0 | .NET 6.0 | 8000 | 19.785 us | 1.1409 us | 3.3640 us | 20.622 us | 1.2817 | 0.0610 | 8056 B |
| Compute | .NET 7.0 | .NET 7.0 | 8000 | 19.950 us | 0.9851 us | 2.9044 us | 20.818 us | 1.2817 | 0.0610 | 8056 B |
- 控制台程序执行测试代码:
public class Program
{
public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<TestBooleanArray>();
}
}