Andy
Andy

Reputation: 4097

Performance of putting together string and char

I wondered if there is any performance impact when I choose to add an one character string or a single char to a constant string.

So I wrote a small Console Application: (.NET 4)

static class Program
{
    const string STR = "string ";

    static void Main()
    {
        var arr = new string[99999999];

        Stopwatch timer = new Stopwatch();

        Console.ReadLine();

        timer.Start();

        //for (uint i = 0; i < 99999999; i++)
        //{
        //  arr[i] = STR + 'C';
        //}

        for (uint i = 0; i < 99999999; i++)
        {
            arr[i] = STR + "C";
        }

        timer.Stop();

        Console.WriteLine(timer.ElapsedMilliseconds);

        Console.ReadLine();
    }
}

You have to comment one for-loop.

So, STR + "C" takes around 1300 ms.

For STR + 'C' I did not see the result yet. It takes too long and seems to bother my computer pretty hard.

So, my question is. How is this performance impact possible? I know an array of 99999999 values won't occur very often in practical usage, but it's still an enormous difference.

Thanks in advance!

Upvotes: 2

Views: 199

Answers (2)

Tigran
Tigran

Reputation: 62248

The simple program like this:

var val = "hello ";     
val += 'r'; 

executes a boxing of char value to object, which we can see from generated IL

IL_0001:  ldstr       "hello "
IL_0006:  stloc.0     // val
IL_0007:  ldloc.0     // val
IL_0008:  ldc.i4.s    72 
IL_000A:  box         System.Char
IL_000F:  call        System.String.Concat
IL_0014:  stloc.0     // val
IL_0015:  ldloc.0     // val

Instead in case of string, there is no any boxing involved, so it's significaly faster.

So why the boxing is executed ? Because calling System.String.Concat(String,String) (that is a result of binary + operator call) on 2 arguments where only one of them is a string, calls overload of String.Concat(object,object), so the value of char is boxed to be able to pass into that method call.

Upvotes: 4

dlev
dlev

Reputation: 48596

This is actually really easy to explain: you've stumbled onto the fact that the C# compiler will perform constant folding on string expressions.

Since you declared STR to be const, that has the effect of replacing references to it with the literal string "string ". Then, when the compiler encounters "string " + "C", it replaces that expression with the equivalent "string C". So the loop that actually finishes is spending all its time assigning that string to different positions in the array.

Conversely, the char concatenation is not optimized that way, so you actually have to wait for both the concatenation (including allocation of the new string object) as well as array assignment. As well, the loop will generate a ton of garbage, so you're also waiting for the collector.

If you want to compare the two operations fairly, I would do two things:

  1. Change the declaration of STR to static readonly instead of const.
  2. Reduce the number of iterations, so that you can actually get a full run-through.

Upvotes: 6

Related Questions