Last active
September 16, 2025 15:16
-
-
Save KyleMit/2199c0df74461d3c9fd562838fd72378 to your computer and use it in GitHub Desktop.
Performance Benchmarks for String Concatenation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Method | Lines | Mean | Ratio | Allocated | | |
|--------------------------------- |------ |---------:|------:|-----------:| | |
| Option_A_Chained_Appends | 10000 | 102.0 us | 0.86 | 935.62 KB | | |
| Option_B_AppendFormat | 10000 | 204.9 us | 1.73 | 1169.99 KB | | |
| Option_C_Interpolated_AppendLine | 10000 | 118.8 us | 1.00 | 935.62 KB | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Text; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Columns; | |
using BenchmarkDotNet.Running; | |
public class Program | |
{ | |
public static void Main(string[] args) | |
=> BenchmarkRunner.Run<StringBuilderSuite>(); | |
} | |
[MemoryDiagnoser] // reports allocations, too | |
[HideColumns( | |
Column.Error, | |
Column.StdDev, | |
Column.RatioSD, | |
Column.AllocRatio, | |
Column.Gen0, | |
Column.Gen1, | |
Column.Gen2)] | |
public class StringBuilderSuite | |
{ | |
// How many lines to build per benchmark. Adjust if you want a longer/shorter run. | |
[Params(10_000)] | |
public int Lines; | |
// Rough preallocation to avoid resize noise; tweak if you change the format a lot. | |
private int EstimatedPerLine => 24; | |
[Benchmark] | |
public string Option_A_Chained_Appends() | |
{ | |
var sb = new StringBuilder(Lines * EstimatedPerLine); | |
for (int i = 0; i < Lines; i++) | |
{ | |
sb.Append("remapping ").Append(i).AppendLine(" synonyms"); | |
} | |
return sb.ToString(); | |
} | |
[Benchmark] | |
public string Option_B_AppendFormat() | |
{ | |
var sb = new StringBuilder(Lines * EstimatedPerLine); | |
for (int i = 0; i < Lines; i++) | |
{ | |
sb.AppendFormat("remapping {0} synonyms", i).AppendLine(); | |
} | |
return sb.ToString(); // prevent dead-code elimination | |
} | |
[Benchmark(Baseline = true)] | |
public string Option_C_Interpolated_AppendLine() | |
{ | |
var sb = new StringBuilder(Lines * EstimatedPerLine); | |
for (int i = 0; i < Lines; i++) | |
{ | |
// On modern .NET, this uses the interpolated string handler => no intermediate string | |
sb.AppendLine($"remapping {i} synonyms"); | |
} | |
return sb.ToString(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment