Tuesday, November 16, 2021

How to use BenchmarkDotNet

If you want to measure the performance of your .NET code, you can use the BenchmarkDotNet NuGet package. Let's see what you can do with it.

The description of your performance tests looks like a usual class:

[SimpleJob(RuntimeMoniker.Net50)]
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
[MinColumn, MaxColumn]
public class HashAlgorithmsComparison
{
    private readonly SHA256 sha256 = SHA256.Create();
    private readonly SHA512 sha512 = SHA512.Create();
    private readonly 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);
    }

    [GlobalCleanup]
    public void Cleanup()
    {
        data = new byte[0];
    }

    [IterationSetup]
    public void IterationSetup()
    {
        Console.WriteLine("Iteration setup");
    }

    [IterationCleanup]
    public void IterationCleanup()
    {
        Console.WriteLine("Iteration cleanup");
    }

    [Benchmark(Baseline = true)]
    public byte[] Md5() => md5.ComputeHash(data);

    [Benchmark]
    public byte[] Sha256() => sha256.ComputeHash(data);

    [Benchmark]
    public byte[] Sha512() => sha512.ComputeHash(data);
}

Each method, which performance must be measured, should be marked with the Benchmark attribute. For one of such attributes you can set Baseline property to true. In this case, this method will be used as a base. The performance of other methods will be compared with this method performance.

Methods marked with GlobalSetup and GlobalCleanup attributes are used for initialization and cleanup for each benchmark method. They'll be executed once for all iterations of this method. Other methods marked with IterationSetup and IterationCleanup attributes will be executed before and after each iteration.

By default BenchmarkDotNet calculates several standard statistics. But you can specify additional statistics to calculate. It is done with attributes like MinColumn and MaxColumn.

You also can execute your tests for different target frameworks. Use attributes like SimpleJob(RuntimeMoniker.NetCoreApp31) and SimpleJob(RuntimeMoniker.NetCore50) to do it. But remember that you have to have SDKs for these frameworks installed on machines where you want to run your tests. BenchmarkDotNet will compile the code for these frameworks.

BenchmarkDotNet also allows to parameterize your tests. You can do it with Params attribute that specifies values which should be assigned to the property marked with this attribute. There are other attributes that allow to take these values from the results of method executions.

As a result of work, BenchmarkDotNet generates several report files (CSV, MD, HTML). You can customize what reports you want to see using attributes like MarkdownExporterAttribute.GitHub.

In order to execute your tests, use the following code:

class Program
{
    static void Main()
    {
        _ = BenchmarkRunner.Run<HashAlgorithmsComparison>();
    }
}

That's all. For additional information, please, refer to the documentation.

No comments:

Post a Comment