views:

559

answers:

8

Recently I have found myself using StringBuilder for all string concatenations, big and small, however in a recent performance test I swapped out a colleague's stringOut = string1 + "." string2 style concatenation (being used in a 10000x + loop with the StringBuilder being newed each time) for a StringBuilder just to see what difference it would make in a minor concatenation.

I found, over many runs of the performance test, the change was both insignificantly higher or lower regardless of concatenation or StringBuilder (restating this was for small concatenations).

At what point does the 'newing up' of a StringBuilder object negate the benefits of using one?

+12  A: 

The rule that I follow is -

Use a StringBuilder when the number of concatenations is unknown at compile time.

So, in your case each StringBuilder was only appending a few times and then being discarded. That isn't really the same as something like

string s = String.Empty;
for (int i = 0; i < 10000; ++i)
{
    s += "A";
}

Where using a StringBuilder would drastically improve performance because you would otherwise be constantly allocating new memory.

Ed Swangren
+3  A: 

Sometimes it's worth looking at the documentation:

The performance of a concatenation operation for a String or StringBuilder object depends on how often a memory allocation occurs. A String concatenation operation always allocates memory, whereas a StringBuilder concatenation operation only allocates memory if the StringBuilder object buffer is too small to accommodate the new data. Consequently, the String class is preferable for a concatenation operation if a fixed number of String objects are concatenated. In that case, the individual concatenation operations might even be combined into a single operation by the compiler. A StringBuilder object is preferable for a concatenation operation if an arbitrary number of strings are concatenated; for example, if a loop concatenates a random number of strings of user input.

In your example, there is only a single concatenation per output string, so StringBuilder gains you nothing. You should use StringBuilder in cases where you are adding to the same string many times, e.g.:

stringOut = ...
for(...)
    stringOut += "."
    stringOut += string2
oefe
+1  A: 

From MSDN:

[T]he String class is preferable for a concatenation operation if a fixed number of String objects are concatenated. In that case, the individual concatenation operations might even be combined into a single operation by the compiler. A StringBuilder object is preferable for a concatenation operation if an arbitrary number of strings are concatenated; for example, if a loop concatenates a random number of strings of user input.

I guess the answer is "it depends" - if you're concatenating inside a loop with more than a handful of iterations then a StringBuilder will almost always deliver better performance, but the only way to know for sure is to actually profile.

LukeH
A: 

There's an interesting article on this over at Coding Horror. Jeff got the following results for 100,000 iterations on a dual core 3.5 GHz Core 2 Duo:

 Simple Concatenation    - 606 ms
 String.Format           - 665 ms
 string.Concat           - 587 ms
 String.Replace          - 979 ms
 StringBuilder           - 588 ms
Sean
yes, but that was with a fixed # of things being concatenated each time. I agree with Ed -- if the # of things being smushed together is inherently VARIABLE, you want a StringBuilder.
Jeff Atwood
OK, so the rule is smushed == StringBuilder. Thanks :)
johnc
+1  A: 

From Dot Net Perls:

When to use StringBuilder?

StringBuilder is entirely an optimization, and it offers no logical improvements to string Concat other than its internal implementation. That said, it is critical to use it correctly in your high-performance applications and web sites.

Sometimes, it is okay to use small loops of 4 or fewer iterations with simple string Concats. However, in edge cases this can be disastrous. Plan for your edge cases with StringBuilder.

ecleel
+4  A: 

I'm sure I've got another answer where I posted just a link to my article and then its summary, but here we go again.

  • Definitely use StringBuilder when you're concatenating in a non-trivial loop - especially if you don't know for sure (at compile time) how many iterations you'll make through the loop. For example, reading a file a character at a time, building up a string as you go using the += operator is potentially performance suicide.

  • Definitely use the concatenation operator when you can (readably) specify everything which needs to be concatenated in one statement. (If you have an array of things to concatenate, consider calling String.Concat explicitly - or String.Join if you need a delimiter.)

  • Don't be afraid to break literals up into several concatenated bits - the result will be the same. You can aid readability by breaking a long literal into several lines, for instance, with no harm to performance.

  • If you need the intermediate results of the concatenation for something other than feeding the next iteration of concatenation, StringBuilder isn't going to help you. For instance, if you build up a full name from a first name and a last name, and then add a third piece of information (the nickname, maybe) to the end, you'll only benefit from using StringBuilder if you don't need the (first name + last name) string for other purpose (as we do in the example which creates a Person object).

  • If you just have a few concatenations to do, and you really want to do them in separate statements, it doesn't really matter which way you go. Which way is more efficient will depend on the number of concatenations the sizes of string involved, and what order they're concatenated in. If you really believe that piece of code to be a performance bottleneck, profile or benchmark it both ways.

Jon Skeet
+1 for not just posting the link, and actually summarizing (solitary link regurgitation is a pet peeve of mine here)
johnc
+1  A: 

My rule of thumb is simple.

  1. If you reasonably can write a single expression that produces the final, then use +.
  2. If you can't (due either to size or variability), then use StringBuilder.

In my experience, expressions such as:

"Id: " + item.id + " name: " + item.name

can be written and understood much more easily than:

StringBuilder sb = new StringBuilder();
sb.append("Id: ").append(item.id);
sb.append(" name: ").append(item.name);

(followed by using the string from sb where the above expression would have been written), and it performs equally well (hint: look at the compiled code to see why!)

On the other hand, when there's need to accumulate a string over time (as the program runs) or space (made up of values coming from different parts of the code), in a way that is impractical to write as a single-line expression, then StringBuilder avoids the overhead (time and memory-churning) of:

String s = somethingExpression;
...
s += someOtherExpression;
...
s += yetAnotherExpression;
...
joel.neely