You are deciding whether to use StringBuilder instead of string when appending string data. At what point does StringBuilder become more efficient? Should you always use StringBuilder?
This is an adjunct article to my other StringBuilder work. What I tested here were tight loops that append a single string each iteration.
| 1. StringBuilder default | 2. StringBuilder with capacity |
| StringBuilder builder1 = new StringBuilder(); for (int i = 1; i < count1; i++) { builder1.Append(s); } string built1 = builder1.ToString(); | StringBuilder builder2 = new StringBuilder(count1 * maxLength); for (int i = 1; i < count1; i++) { builder2.Append(s); } string built2 = builder2.ToString(); |
| • Uses StringBuilder with no capacity • Loops over number of strings • ToString used at end | • Uses StringBuilder with capacity • Capacity value is 100% accurate • Otherwise same as 1 |
Next is the regular string.Concat code:
| 3. String concat |
| string st1 = string.Empty; for (int i = 1; i < count1; i++) { st1 += s; } |
| • Uses string reference type • string.Concat is used |
My test tried to defeat every compiler optimization by using different strings of the same lengths to append. The tests were repeated 20 times more for counts below 8 strings.
My benchmark indicates that using the string reference type with Concat is faster for 1 to 4 strings inclusive. Using StringBuilder with an accurate capacity is faster than StringBuilder always.
Use StringBuilder always when you have a loop of a variable length. This will make your program usable in more scenarios than string Concat will.
For example, if you have a program that has three strings 99% of the time, but 30,000 strings 1% of the time, using StringBuilder will make the program usable in that 1%.
As always, one of the most important parts of good programming is planning for errors and edge cases.
Obviously, if your program is lightning fast 99% of the time, but fails 1% of the time, your program is unacceptable for important work. Therefore, I think StringBuilder is preferrable in most loops.
There are many problems to this test. The individual strings themselves were 20 characters long. This may not match many programs in the real world. Most programs have strings of variable length.
I didn't benchmark cases where there are hundreds of thousands of strings. However, it is clear to me that the trend of the lines would continue.
The capacity settings I used were always 100% accurate, which in real-world programs might be unlikely. However, I feel the findings here encourage using capacities. [C# - Capacity Tests - dotnetperls.com]
The source code of the benchmark will be available on my code site, but hasn't been placed there yet. You could construct the benchmark from my code examples at the top.
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 correctly in your high-performance apps 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.