Çarşamba, Kasım 07, 2007

Word of advise for string concats

now that the subject came up at the training session at koc-sistem today, i thought I'd mention it, because i have seen this mistake made by novice/lazy programmers quite a lot.
String concatenation in loops using literal strings and the + operator is an expensive operation. This is because every time a new string object is created. Consider the following code:

string x = "";
for (int i=0;i<100000;i++)
{
x += "!"+i
}

This heart of the loop would actually translate into x = x+"!"+i. Because strings are immutable in Csharp.NET every iteration, a new object is created which has the value of the old string and the "!" and the value of i, and the memory reference is assigned to the variable x. The old value of x and the new values are copied each time, which makes this an expensive operation. And there are lots of garbage hanging around the heap which degrades the performance even more when the garbage collector is invoked.
With each iteration the amount of data copied increases exponentially, if we double the iteration count, the loop would take much more than twice the time to execute. So the solution to this problems comes with the StringBuilder object. Consider the following code:

StringBuilder builder = new StringBuilder();
for (int i=0; i < 100000; i++)
{
builder.append("!");
builder.append(i.ToString());
}
builder.ToString();

What happens here is that the StringBuilder object gets some memory and really appends the data during the execution of the loop. The whole string doesn't get copied, just the part that gets appended. StringBuilder maintains an internal buffer for this, and only copies to a new object where this buffer needs to be expanded (Strings are immutable from a public interface but not within the core libraries).

So go ahead and change every single concatenation to a StringBuilder? No! There is a saying in Turkish which roughly translates to "extracting the shit out of something".
We just need to use the StringBuilder when are doing extensive concatenation operations. Don't do the following:

string name = firstName + " " + lastName;

substitute with

StringBuilder builder = new StringBuilder();
builder.Append (firstName);
builder.Append (" ");
builder.Append (lastName);

There are the following drawbacks:
The second piece of code is very unreadable.
The second piece of code is not more efficient that the first, because the first piece actually translates into String.Concat() (Assuming that firstName and lastName are real variables and not constants) and that method can cope with the data without having to copy everything to a new object.
So it just doesn't justify.

Using constants in concatenations is a different story. The compiler is smart enough to know at compile time that

string x = "hello" + " " + "there";

is actually

string x = "hello there";

and does this transformation automatically.
So to sum things up:
Use StringBuilder if you are concatenating string extensively in a loop.

1 yorum:

Enver ALTIN dedi ki...

Well, I think you can override the "+=" operator so it will look like this:

StringBuilder sb = new StringBuilder();
sb += "some string here";

and I guess this is probably done already, just because it looks too beautiful to not to implement in the core.