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 enstring
er oprettet, kan den ikke ændres. Når man udfører operationer, der ændrer enstring
, oprettes der faktisk en nystring
objekt hver gang. Dette kan føre til ydeevneproblemer i situationer, hvor der er behov for mange ændringer på enstring
. -
StringBuilder :
StringBuilder
klassen er designet til at håndtere situationer, hvor der er behov for mange ændringer på en tekststreng. I modsætning tilstring
erStringBuilder
en foranderlig type, hvilket betyder, at den kan ændres uden at oprette nye objekter. Dette gørStringBuilder
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:
eller fra konsole:
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.