Home > Software design >  Why C# string interpolation slower than regular string concat?
Why C# string interpolation slower than regular string concat?

Time:07-10

I am optimizing our debug print facilities (class). The class is roughly straightforward, with a global "enabled" bool and a PrineDebug routine.

I'm investigating the performance of the PrintDebug method in "disabled" mode, trying to create a framework with less impact on run time if no debug prints are needed.

During the exploration I came across the below results, which were a surprise to me and I wonder what am I missing here?

public class Profiler
{
     private bool isDebug = false;

     public void PrineDebug(string message)
     {
         if (isDebug)
         {
             Console.WriteLine(message);
         }
     }
}

[MemoryDiagnoser]
public class ProfilerBench
{
    private Profiler profiler = new Profiler();
    private int five = 5;
    private int six = 6;

    [Benchmark]
    public void DebugPrintConcat()
    {
        profiler.PrineDebug("sometext_"   five   "_"   six);
    }

    [Benchmark]
    public void DebugPrintInterpolated()
    {
        profiler.PrineDebug($"sometext_{five}_{six}");
    }
}

Running this benchmark under BenchmarkDotNet.. Here are the results:

|                 Method |     Mean |   Error |  StdDev |  Gen 0 | Allocated |
|----------------------- |---------:|--------:|--------:|-------:|----------:|
|       DebugPrintConcat | 149.0 ns | 3.02 ns | 6.03 ns | 0.0136 |      72 B |
| DebugPrintInterpolated | 219.4 ns | 4.13 ns | 6.18 ns | 0.0181 |      96 B |

I thought the Concat approach will be slower as every operation actually creates a new string ( allocation), but seems the interpolation caused higher allocation with higher time.

Can you explain?

CodePudding user response:

String concatenation is faster and lighter when you have to concatenate less than 4-8 (not accurate though) strings, but as the number of strings which has to be concatenated grows, it's better to use StringBuilder StringBuilder.

Internally, when you concatenate strings using ' ' operator like

string test = "foo"   a   "bar";

the concat() method is called for every concatenation.

string t1 = "foo";
string t2 = a;
string t3 = concat(t1, t2);
string t4 = "bar";
string final = concat(t3, t4);

In the latter case for string interpolation, which is nothing but a syntactic sugar for String.Format().

So, when you use string interpolation,

string text = $"Foo{a}Bar";

it would be converted to,

string text = string.Format("Foo{0}Bar", new object[] { a });

You can find performance implications of these methods in the MSDN, however, the performance factor is pretty much negligible in small scale string building, but for serious string building, it's much better to use a StringBuilder rather than interpolation and raw concatenation.

Performance cannot be the only factor while picking an approach, because interpolation internally calls string.Format() which allows you to format your string (padding, decimal precision, date formatting, etc) offering you much more flexibility.

Concatenation, Formatting and String building has their own use cases, it is up to you to decide which one suits your need the best.

CodePudding user response:

I believe that problem here is just a boxing of ints. I tried to eliminate the boxing and got the same performance as for concatenation

Method Mean Error StdDev Gen 0 Allocated
DebugPrintConcat 41.49 ns 0.198 ns 0.185 ns 0.0046 48 B
DebugPrintInterpolated 103.07 ns 0.257 ns 0.227 ns 0.0092 96 B
DebugPrintInterpolatedStrings 41.36 ns 0.211 ns 0.198 ns 0.0046 48 B

DebugPrintInterpolatedStrings code: I just added explicit ToString

    [Benchmark]
    public void DebugPrintInterpolatedStrings()
    {
        profiler.PrineDebug($"sometext_{five.ToString()}_{six.ToString()}");
    }

We can also note the reduced allocations (exactly because of absence of additional boxed objects).

PS. By the way, @GSerg already mentioned post with the same explanation in the comment.

  • Related