Gå til indholdet

Introduktion til BenchmarkDotNet

BenchmarkDotNet er et populært og alsidigt benchmarking-bibliotek til .NET, der hjælper udviklere med at måle og sammenligne ydeevnen for deres kode. I denne artikel kan du se et eksempelvis på hvordan man bruger BenchmarkDotNet til at sammenligne ydeevnen mellem string og StringBuilder klasserne i C#.

Hvad er BenchmarkDotNet?

BenchmarkDotNet er et open-source bibliotek, der gør det nemt at skrive og køre benchmarks i .NET. Det automatiserer mange aspekter af benchmarking-processen og giver detaljerede resultater og statistikker. BenchmarkDotNet er et værdifuldt værktøj, når man ønsker at forstå, hvilke dele af koden der kan optimeres for bedre ydeevne. - BenchmarkDotNet på GitHub

String vs. StringBuilder

Før der dykkes ned i benchmarking, lad os kort forstå forskellen mellem string og StringBuilder klasserne i C#.

  • String : I .NET er string en uforanderlig type, hvilket betyder, at når en string er oprettet, kan den ikke ændres. Når man udfører operationer, der ændrer en string, oprettes der faktisk en ny string objekt hver gang. Dette kan føre til ydeevneproblemer i situationer, hvor der er behov for mange ændringer på en string.

  • StringBuilder : StringBuilder klassen er designet til at håndtere situationer, hvor der er behov for mange ændringer på en tekststreng. I modsætning til string er StringBuilder en foranderlig type, hvilket betyder, at den kan ændres uden at oprette nye objekter. Dette gør StringBuilder mere effektiv i scenarier, hvor der er behov for mange ændringer på en tekststreng.

Opsætning af BenchmarkDotNet

Først skal BenchmarkDotNet-biblioteket tilføjes til projektet ved hjælp af NuGet:

Her i VS:

Install-Package BenchmarkDotNet

eller fra konsole:

dotnet add package BenchmarkDotNet

Skriv benchmark-koden

Opret en ny klasse kaldet StringVsStringBuilderBenchmark, og tilføj følgende kode:

using System.Text;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

[MemoryDiagnoser]
public class StringVsStringBuilderBenchmark
{
    private const int AntalSammenkoblinger = 1000;

    [Benchmark]
    public string StringSammenkobling()
    {
        string resultat = string.Empty;

        for (int i = 0; i < AntalSammenkoblinger; i++)
        {
            resultat += "a";
        }

        return resultat;
    }

    [Benchmark]
    public string StringBuilderSammenkobling()
    {
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < AntalSammenkoblinger; i++)
        {
            stringBuilder.Append("a");
        }

        return stringBuilder.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<StringVsStringBuilderBenchmark>();
    }
}

I dette eksempel er der to benchmark-metoder: StringSammenkobling og StringBuilderSammenkobling. Begge metoder udfører den samme operation - sammenkobling af en tekststreng 1000 gange - men den første metode bruger string, mens den anden metode bruger StringBuilder.

[Benchmark] attributten bruges til at markere metoder, der skal benchmarkes af BenchmarkDotNet. Programmet kører derefter benchmarket ved hjælp af BenchmarkRunner.Run<StringVsStringBuilderBenchmark>() i Main-metoden.

Kør benchmarket og analyser resultaterne

Når koden er skrevet, kan benchmarket køres ved at starte programmet. BenchmarkDotNet vil automatisk køre hver benchmark-metode flere gange og beregne gennemsnitlige køretider, standardafvigelser og andre statistikker.

Resultaterne vises i konsollen og kan også eksporteres til forskellige formater, såsom HTML, CSV eller Markdown. Disse resultater vil hjælpe med at forstå, hvilken metode der er hurtigere, og om string eller StringBuilder bør anvendes i en bestemt situation.

Method Mean Error StdDev Gen0 Allocated
StringSammenkobling 126.512 us 1.9704 us 3.5024 us 653.8086 1001.93 KB
StringBuilderSammenkobling 5.365 us 0.1042 us 0.1622 us 2.9144 4.47 KB

Her er en forklaring på tabellen:

Navn Beskrivelse
Method Navnet på den metode, der blev benchmarket.
Mean Gennemsnitlig eksekveringstid for metoden i løbet af alle kørsler.
Error Fejlmargen for den gennemsnitlige eksekveringstid (± intervallet).
StdDev Standardafvigelsen, der viser spredningen af eksekveringstiderne for metoden.
Gen0 Antallet af generation 0 GC (Garbage Collection) operationer udført under benchmarket.
Allocated Den samlede mængde hukommelse (i byte), der blev tildelt af metoden under benchmarket.

I dette eksempel er StringBuilderSammenkobling være meget hurtigere end StringSammenkobling, da StringBuilder er designet til at være mere effektiv til sammenkobling af tekststrenge.

Info

“us” står for mikrosekunder (microseconds) i resultatet af en benchmark. En mikrosekund er en milliontedel af et sekund, hvilket betyder, at der er 1.000.000 mikrosekunder i ét sekund. Mikrosekunder bruges ofte til at måle og rapportere præstationsmålinger i benchmarking, da de giver en mere præcis repræsentation af tidsforbruget for en given operation sammenlignet med millisekunder (en tusindedel af et sekund) eller sekunder.

Opgaver