你是否经常因为以下问题而苦恼:
如果你还在用DateTime.Now或Stopwatch手写性能测试,那你很可能已经掉进了性能测试的十大陷阱!今天给大家介绍一个被.NET官方团队、Roslyn编译器团队等27000+项目采用的专业性能测试库——BenchmarkDotNet。
大多数开发者习惯这样测试性能:
c#// ❌ 错误示范 - 这样测试结果不可信!我基本这么用了,大概齐吧。
var sw = Stopwatch.StartNew();
for (int i = 0; i < 1000; i++)
{
MyMethod();
}
sw.Stop();
Console.WriteLine($"耗时: {sw.ElapsedMilliseconds}ms");
这种做法存在以下严重问题:

安装命令:
bashdotnet add package BenchmarkDotNet
最简单的使用示例:
c#using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Text;
namespace AppBenchmarkDotNet
{
[SimpleJob]
[RPlotExporter] // 自动生成性能图表
public class StringConcatBenchmark
{
private const int N = 10000;
private readonly string[] data = new string[N];
[GlobalSetup]
public void Setup()
{
for (int i = 0; i < N; i++)
data[i] = $"Item{i}";
}
[Benchmark(Baseline = true)]
public string StringConcat()
{
string result = "";
foreach (var item in data)
result += item;
return result;
}
[Benchmark]
public string StringBuilder()
{
var sb = new StringBuilder();
foreach (var item in data)
sb.Append(item);
return sb.ToString();
}
[Benchmark]
public string StringJoin()
{
return string.Join("", data);
}
}
internal class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<StringConcatBenchmark>();
}
}
}

三种方法的性能对比:
常见坑点提醒:
⚠️ 确保项目运行在Release模式,否则BenchmarkDotNet会警告并拒绝运行
⚠️ 不要在调试器附加状态下运行测试
c#[SimpleJob]
public class CollectionBenchmark
{
[Params(100, 1000, 10000)] // 自动测试不同数据量
public int DataSize;
private int[] data;
[GlobalSetup]
public void Setup()
{
data = Enumerable.Range(0, DataSize).ToArray();
}
[Benchmark]
public int[] ArrayCopy()
{
var result = new int[data.Length];
Array.Copy(data, result, data.Length);
return result;
}
[Benchmark]
public int[] LinqToArray()
{
return data.ToArray();
}
[Benchmark]
public List<int> ToList()
{
return data.ToList();
}
}

实际应用场景:
c#[SimpleJob(RuntimeMoniker.Net48, baseline: true)]
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net80)]
[RPlotExporter]
public class CrossPlatformBenchmark
{
[Params(1000, 10000)]
public int N;
private byte[] data;
[GlobalSetup]
public void Setup()
{
data = new byte[N];
Random.Shared.NextBytes(data);
}
[Benchmark]
public string ToBase64()
{
return Convert.ToBase64String(data);
}
[Benchmark]
public byte[] FromBase64()
{
var base64 = Convert.ToBase64String(data);
return Convert.FromBase64String(base64);
}
}

c#[SimpleJob]
[MemoryDiagnoser] // 开启内存诊断
public class MemoryBenchmark
{
[Benchmark]
public string StringInterpolation()
{
return $"Hello {"World"}!";
}
[Benchmark]
public string StringFormat()
{
return string.Format("Hello {0}!", "World");
}
[Benchmark]
public string StringConcat()
{
return "Hello " + "World" + "!";
}
}
内存诊断结果:
markdown| Method | Mean | Allocated | |-------------------- |---------:|----------:| | StringInterpolation | 15.23 ns | 32 B | | StringFormat | 45.67 ns | 56 B | | StringConcat | 12.89 ns | 32 B |
c#[Config(typeof(CustomConfig))]
public class AdvancedBenchmark
{
// 自定义配置类
public class CustomConfig : ManualConfig
{
public CustomConfig()
{
AddJob(Job.Default
.WithRuntime(ClrRuntime.Net48)
.WithPlatform(Platform.X64)
.WithGcServer(true)); // 服务器GC
AddExporter(HtmlExporter.Default);
AddExporter(CsvExporter.Default);
AddDiagnoser(MemoryDiagnoser.Default);
AddColumn(StatisticColumn.P95); // 95分位数
}
}
[Benchmark]
[Arguments(100)]
[Arguments(1000)]
public void ProcessData(int count)
{
// 处理逻辑
for (int i = 0; i < count; i++)
{
Math.Sqrt(i);
}
}
}
c#[SimpleJob, MemoryDiagnoser, RPlotExporter]
public class ApiBenchmark
{
[Params(100, 1000)] public int RequestCount;
[Benchmark(Baseline = true)] public void OldApi() { }
[Benchmark] public void NewApi() { }
}
c#[SimpleJob, RankColumn, RPlotExporter]
public class AlgorithmBenchmark
{
[Params(10, 100, 1000)] public int DataSize;
[Benchmark] public void BubbleSort() { }
[Benchmark] public void QuickSort() { }
}
c#[SimpleJob, MemoryDiagnoser]
public class MemoryOptimizationBenchmark
{
[Benchmark(Baseline = true)] public void Original() { }
[Benchmark] public void Optimized() { }
}
通过今天的分享,希望你能掌握以下三个关键点:
BenchmarkDotNet不仅仅是一个测试工具,更是帮助你建立性能意识和数据驱动思维的利器。当你的代码性能有了量化的依据,优化方向就变得清晰可见。
你在项目中遇到过哪些性能难题? 或者你最想测试哪种场景的性能? 欢迎在评论区分享你的经验和问题!
如果这篇文章对你有帮助,请转发给更多同行,让我们一起用数据说话,写出更高性能的C#代码!
#C#开发 #性能优化 #编程技巧 #BenchmarkDotNet #软件工程
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!