Benchmarking .NET 5 code with BenchmarkDotNet
Posted: (EET/GMT+2)
If you need to measure performance changes in .NET 5 code, one of the easiest ways is to use a new tool called BenchmarkDotNet. It is a benchmarking library for .NET applications that handles warmup runs, iterations, statistics, and many of the common mistakes found in hand-written benchmarks.
You can add the functionality as a NuGet package to your application. For example, using dotnet add package:
dotnet add package BenchmarkDotNet
Then create a simple benchmark class and apply the attributes:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
public class StringBenchmarks
{
[Benchmark]
public string StringConcat()
{
return "Hello" + " " + "world";
}
[Benchmark]
public string StringInterpolation()
{
return $"{ "Hello" } { "world" }";
}
}
public class Program
{
public static void Main(string[] args)
{
BenchmarkRunner.Run<StringBenchmarks>();
}
}
Run the benchmark in Release mode:
dotnet run -c Release
The tool creates a detailed summary including execution time, standard deviation, allocation data, and comparisons between methods.
Tip: always benchmark Release builds. BenchmarkDotNet warns about Debug builds because the results are usually unreliable.
A useful feature is the memory diagnoser, which helps detect unnecessary allocations:
[MemoryDiagnoser]
public class StringBenchmarks
{
// put your benchmarks here
}
This adds allocation statistics directly to the benchmark results.
BenchmarkDotNet also supports comparing multiple runtimes. During the .NET 5 timeframe, this is handy for checking differences between .NET Core 3.1 and .NET 5, for instance. Something along these lines:
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
[SimpleJob(RuntimeMoniker.Net50)]
public class StringBenchmarks
{
// your benchmarks go here
}
For performance-sensitive ASP.NET Core or backend code, having repeatable benchmarks makes it much easier to validate whether a change actually improves throughput or just "feels" faster.
Happy hacking!