IPerformance Vergleich String Concat über + Operator v. StringBuilder
Ich wollte schon immer mal wissen, was welche Methode der String Bildung eigentlich performanter ist. Das verbinden über den + Operator oder die Nutzung der StringBuilder Klasse. Dafür habe ich ein wenig Code zusammengestrickt.
Als Performance Analyse Tool benutze ich BenchmarkDotNet. Ein sehr einfaches Tool, um sowohl die Speicherauslastung als auch die verwendete Zeit zu messen.
Darüber hinaus benutze ich auch noch ein Tool, welches die Ergebnisse in einer coolen Form darstellt.
Als aller erstes habe ich einen Consolen Client erstellt. Darin enthalten zwei Klassen. Zum einen die Klassen, wo dann die Performance Dekoration erfolgt. Bedeutet, dass dort die Methoden, die untersucht werden sollen, enthalten sind. Diese Klasse sieht so aus:
using BenchmarkDotNet.Attributes;
using System.Text;
namespace ConsolePerf;
[MemoryDiagnoser]
public class PerformanceClass
{
[Params(4, 100, 10_000, 100_000)]
public int Size;
public string[] AllStrings { get; set; }
[IterationSetup]
public void Setup()
{
AllStrings = StringArrayGenerator.Generate(Size, „hello!“, „HELLO!“);
}
[Benchmark]
public void PerfStringBuilder()
{
var sb = new StringBuilder();
foreach (var s in AllStrings)
{
sb.Append(s);
}
var finalString = sb.ToString();
}
[Benchmark]
public void PerfConcatenation()
{
var finalString = string.Empty;
foreach (var s in AllStrings)
{
finalString += s;
}
}
}
Dekorationen:
[MemoryDiagnoser] == Diese Dekoration liefert sowohl Zeit- als auch Speicherinformationen.
[IterationSetup] == Diese Methode wird vor jeder Ausführung aufgerufen, nimmt das Value vom Size Property und initialisiert das AllStrings Array.
[Params] == Die möglichen Values des Size Properties, welches bei der Execution die unterschiedlichen Arrays durchläuft.
[Benchmark] == Die zu untersuchenden Methoden.
Die zweite Klasse ist der StringArrayGenerator, der die Dummy Daten erzeugt. Diese Klasse sieht so aus:
using Bogus;
namespace ConsolePerf;
public static class StringArrayGenerator
{
public static string[] Generate(int size, params string[]? additionalStrings)
{
var array = new string[size];
var faker = new Faker();
List fixedValues = [
string.Empty,
“ „,
„\n \t“,
null!
];
if (additionalStrings != null)
{
fixedValues.AddRange(additionalStrings);
}
for (var i = 0; i < array.Length; i++)
{
if (Random.Shared.Next() % 4 == 0)
{
array[i] = Random.Shared.GetItems(fixedValues.ToArray(), 1).First();
}
else
{
array[i] = faker.Lorem.Word();
}
}
return array;
}
}
Hier benutze ich Bogus zur Datengenerierung.
GitHub – bchavez/Bogus: :card_index: A simple fake data generator for C#, F#, and VB.NET. Based on and ported from the famed faker.js.
Dann die Consolen Anwendung im Release Modus starten.
using BenchmarkDotNet.Running;
using ConsolePerf;
var summary = BenchmarkRunner.Run();
Dann das Ergebnis (hier Weiß hinterlegt) in das Control auf der WebSite:
Charts for BenchmarkDotNet
einfügen.
Das Ergebnis sieht dann so aus:
Interpretation der Ergebnisse:
Wenn es nur wenige Strings sind, die zusammengefügt werden sollen, ist der + Operator sowohl in der Zeit als auch in der Memory Allokierung besser. Ab 5-6 Strings, die man zusammenführt, kann man dann auf den StringBuilder setzen.