The truth about string concatenation performance...
Here is a riddle, what is faster?
- string str = "Id: " + i;
- string str = string.Format("Id: {0}", i);
- string str = new StringBuilder().Append("Id: ").Append(i).ToString();
If you guess StringBuilder or string.Format, you are mistaken. Over 10 million iterations, the simple "Id: " + i finished in 4.7 seconds, StringBuilder in 5.7 seconds and string.Format in 7.6 seconds.
The reason for that is that the compiler can optimize the + operator to a call to string.Concat, and it does it quite often when you have several parameters. The optimizations of StringBuilder only shows up if you have several concatenations, or if you are using it on more than a single expression.
Comments
The rule of thumb that I use is that if you're just concatenting two or three strings, just use the '+' operator or String.Concat.
String.Format, while slow, sure is handy.
Back in the 1.1 days, it was up 4 values that would be optimized to a call to Concat:
http://weblogs.asp.net/kdente/archive/2003/08/27/25579.aspx
Don't know if that changed for 2.0 though.
Either which way, mostly a micro-optimization, though. ;)
Honestly this isn't too surprising if you think about what is being done. In the first instance, it's a simple string concat, as Oren mentions. For #2, you need to parse out the {0}. I find it amazing that the perf is the same order of magnitude. For #3, you have to allocate a StringBuilder object. As I recall, the break-even for StringBuilder is about a dozen concatentations. Fewer than that and your perf is dominated by allocation of the StringBuilder object. One advantage of StringBuilder is that it reduces the number of temporary strings that have to be allocated as it maintains an internal buffer, which is grown on an as-needed basis. Remember that premature optimization is the root of all evil. Fast enough and maintainable is better than blazingly fast and cryptic, IMHO.
I think I remember reading that somewhere around 4-8 concats it becomes more performant to use the stringbuilder.
Here is an article talking about it:
http://www.heikniemi.net/hc/archives/000124.html
The point of StringBuilder is that it's much faster when dealing with large blocks of text.
[)amien
Ha... by default, Resharper suggests string.format rewrites over concatenations.
If only the aspnet compiler or some preprocessor would translate string.formats into concatenations :P
Make no sense to have
string str = new StringBuilder()
in the iteration. Usually at the end of the loop you call the ToString() of the StringBuilder object.
"...The optimizations of StringBuilder only shows up if you have several concatenations..." Right!
To elaborate:
You need a new string every iteration in the loop. As 'Tommaso Caldarola' states, StringBuilder makes more sense if you want to have one string built over the whole loop.
And you can see the real difference! I think this loop will take ages to run for a string concatenation.
Sendhil
Good old StringBuilder and its inbuilt idiot detector.
If you hear someone telling you how your concatenation of three strings should be done using StringBuilder, you know instantly they're an idiot.
The Concat method can (and will) determine the size of the resulting string in advance, so only one allocation needs to be done. (They add one alloc by copying the whole array into another array where null gets replaced by String.Empty though.)
StringBuilder has no advance knowledge of the required result buffer size and has to reallocate each time the buffer size is exceeded. Without measuring, I don't see why StringBuilder should have better performance compared to String.Concat for larger sizes. I guess unless you guess the buffer size right and pass it to the StringBuilder ctor, the opposite should be true.
I'm also surprised that String.Format plays in the same league. I think I tested it myself once and found it to be really slow.
Oren: I don't see why String.Concat(s1,s2) should be any faster than String.op_Addition(s1,s2) (except that op_Addition is not defined for String). Performance advantages start with 3 arguments, i.e. String.Concat(s1,s2,s3) instead of String.op_Addition (String.op_Addition(s1,s2),s3).
BTW, String.Concat gets called for any number of arguments, I just tested it.
oren:
It's the KISS principle in action. Use StringBuilder in a loop or somewhere that makes sense. Use + when you just need something quick and simple. Don't try to needlessly complicate your code for the sake of performance... Why, oh why, do certain devs think that maintainability should be sacrificed for a tiny percentage of a performance gain (which, as this post points out, is usually a net loss)?
I vote for option 4:
string str = "Id: " + i.ToString();
That way it calls the Concat(string[]) method instead of Concat(object[]).This means:
1) No need to call ToString on "Id: "
2) No boxing
It only saves about 5% over the 10 million iterations, but if we're microbenchmarking we might as well go for all we can :)
Jon
Comment preview