Why does running the benchmark on the code below, show no memory allocation on method BuildString
? I don't get it, because as far as I know the string should be allocated on the heap.
[MemoryDiagnoser]
public class StringBenchmark
{
[Benchmark]
public string BuildString()
{
return "Test";
}
[Benchmark]
public string BuildStringUsingStringConcatenationMethod()
{
return string.Concat("Hello", 2022, "/", 5);
}
}
The benchmark results:
Method | Mean | Error | StdDev | Gen0 | Allocated |
---|---|---|---|---|---|
BuildString | 0.0000 ns | 0.0000 ns | 0.0000 ns | - | - |
BuildStringUsingStringConcatenationMethod | 60.0764 ns | 0.4336 ns | 0.3385 ns | 0.0286 | 240 B |
The compiler is free to use "interned" strings for literals, i.e. every time you use "abc"
in your code, it can use the same instance of "abc"
. This includes expressions that the compiler can evaluate to constants during build, for example concatenation of other constant expressions.
You can check this:
using System;
string a = Strings.Fixed(), b = Strings.Fixed(),
c = Strings.New(), d = Strings.New();
// writes "abc; equal? True; same? True"
Console.WriteLine($"{a}; equal? {string.Equals(a,b)}; same? {ReferenceEquals(a,b)}");
// writes "def; equal? True; same? False"
Console.WriteLine($"{c}; equal? {string.Equals(c,d)}; same? {ReferenceEquals(c,d)}");
static class Strings
{
// returns interned instance
public static string Fixed() => "abc";
// creates a new instance each time
public static string New() => new string("def".AsSpan());
}