Wenn es um Performance in .net geht dann ist String.Create ein Freund. String.Create kreiert einen String sehr schnell und mit minimalen Speicher overhead.
Gerade wenn es um Performance geht, ist String immer ein kleines Hinderniss. Das hat auch damit zu tun wie Strings in .NET definiert sind.
Zur Erinnerung:
- Strings sind Referenztypen und ihre Daten werden auf dem verwalteten Heap gespeichert.
- Strings sind von Haus aus unveränderlich, was bedeutet, dass ihre Daten nach der Erstellung nicht mehr geändert werden können.
Schauen wir uns das mal mittels eines Beispiels an
normal
public string GenerateShortCode_Classic()
{
var random = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
return new string(Enumerable.Repeat(chars, 6)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
vs
String.create
public string GenerateShortCode_StringCreate()
{
var random = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
string result = string.Create(6, chars, (chars, buf) =>
{
for (int i = 0; i < chars.Length; i++) chars[i] = buf[random.Next(buf.Length)];
});
return result;
}
Abgesehen davon das die String klassische Variante vielleicht lesbarer ist machen die zwei Beispiele das gleiche – es wird ein zufälliger sechs Zeichen langer String erzeugt.
Aber der Benschmark:
Method | Mean | Error | StdDev |
---|---|---|---|
GenerateShortCode_Classic | 252.2 ns | 4.80 ns | 7.76 ns |
GenerateShortCode_StringCreate | 167.8 ns | 3.42 ns | 4.45 ns |
zeigt das String.Create deutlich schneller ist.
Eine interessante Funktion bei String.Create ist
public static string Create (IFormatProvider? provider, ref System.Runtime.CompilerServices.DefaultInterpolatedStringHandler handler);
Dies kann folgender maßen verwendet werden
public string FormatProvider_StringCreate()
{
IFormatProvider formatProvider = CultureInfo.GetCultureInfo("en-US");
string name = "Alice";
int age = 30;
decimal balance = 1234.56m;
// Use String.Create with the IFormatProvider, a Span<char> for direct memory manipulation, and DefaultInterpolatedStringHandler
string result = String.Create(formatProvider, $"{name} is {age} years old and has a balance of {balance:C}.");
return result;
}
public string FormatProvider_ToString()
{
IFormatProvider formatProvider = CultureInfo.GetCultureInfo("en-US");
string name = "Alice";
int age = 30;
decimal balance = 1234.56m;
// Use String.Create with the IFormatProvider, a Span<char> for direct memory manipulation, and DefaultInterpolatedStringHandler
string result = String.Format(formatProvider, "{0} is {1} years old and has a balance of {2:C}", name, age, balance);
return result;
}
Method | Mean | Error | StdDev | Median | Gen0 | Allocated |
---|---|---|---|---|---|---|
FormatProvider_StringCreate | 206.1 ns | 7.34 ns | 21.19 ns | 199.2 ns | 0.0191 | 160 B |
FormatProvider_ToString | 228.9 ns | 4.48 ns | 3.74 ns | 228.4 ns | 0.0257 | 216 B |
Auch hier zeigt sich eine Verbesserung der Performance, jedoch auch das weniger Bytes verwendet werden.
String.Create
plus Punkte:
- Schneller
- Weniger Speicher
minus Punkte
- Lesbarkeit
Source Code: gpiwonka/StringCreateTester: A small benchmark and test for String.Create (github.com)
Schreibe einen Kommentar