Dot Net Perls

StringBuilder Performance Test in C#

by Sam Allen - Updated June 13, 2009

Problem. You are deciding whether to use StringBuilder instead of string when appending string data. Determine the point at which StringBuilder becomes more efficient. Solution. Here we see benchmarks of StringBuilder and strings, and discuss the important considerations when choosing between the two.

StringBuilder performance

1. Benchmarking StringBuilder

Here we see the code styles that were benchmarked to produce the graph. This is an adjunct article to the author's other StringBuilder work. What was tested here were tight loops that append a single string each iteration. The number of strings that were appended was steadily increased to determine the slope of the graph.

=== StringBuilder default code [RED line] ===
    Uses StringBuilder with no capacity
    Loops over number of strings
    ToString method used at end

StringBuilder builder1 = new StringBuilder();
for (int i = 1; i < count1; i++)
{
    builder1.Append(s);
}
return builder1.ToString();

=== StringBuilder with capacity [PURPLE line] ===
    Capacity value is accurate

StringBuilder builder2 = new StringBuilder(count1 * maxLength);
for (int i = 1; i < count1; i++)
{
    builder2.Append(s);
}
return builder2.ToString();

=== String concat [BLUE line] ===
    Uses overloaded operator + for string.Concat

string st1 = string.Empty;
for (int i = 1; i < count1; i++)
{
    st1 += s;
}
return st1;

StringBuilder benchmark results. 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. [See graph above]

The author's interpretation. 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.

2. Best practices with StringBuilder

Here we look at what the author thinks the best way to use StringBuilder is. 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.

An example of the guideline. 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.

Warning for algorithmic inefficiencies. 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 preferable in most loops.

3. Weaknesses of this benchmark

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.

More weaknesses of the test. 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 Property - dotnetperls.com]

4. Summary

Here we saw some factors that will influence when you want to use StringBuilder in your C# programs. 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.

Looping with string type. 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.

Dot Net Perls
StringBuilder | StringBuilder Append Syntax | StringBuilder Equals Method | StringBuilder Mistake | StringBuilder Secrets | StringWriter Use
C# | Dictionary StringComparer Tip | DateTime.TryParse Example | Reflection Field Example | Validate Characters in String
© 2009 Sam Allen. All rights reserved.