Reputation: 4097
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
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
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:
STR
to static readonly
instead of const
.Upvotes: 6