Select Page

Here’s a few general guidelines when working with strings:

  • Don’t concatenate strings – use a StringBuilder instead
  • Whenever possible initialize the StringBuilder with enough capacity to avoid re-allocations
  • Excessive concatenation of strings will be several orders of magnitude slower than using a StringBuilder
  • String.Format() & StringBuilder.AppendFormat() are significantly slower than just using the +operator or Append() – but may be more readable
  • When performance optimizing an application – string usage is a good place to start

Don’t concatenate strings

The StringBuilder is an often overlooked class, that can be used to solve a lot of performance problems in your applications.
To give an example of how ineffective the basic string can be, take a look at the following code that builds 2 large strings by concatenating 1000 times to the same string using String and StringBuilder:

string s = string.Empty;
for (int j = 0; j < 1000; j++)
  s += "Test of string performance.";

StringBuilder sb = new StringBuilder();
for (int j = 0; j < 1000; j++)
  sb.Append("Test of string performance.");

Performance is measured on my HTC S710 moblie phone. The performance difference is very noticeable.

  • The String implementation takes about 800ms
  • The StringBuilder implementation takes about 12ms

StringBuilder is almost 70 times faster than String in this particular example and initializing the StringBuilder with enough capacity up front will shave another 2ms off. I have done tons of optimizations on Compact Framework applications over the years, and the first thing i usually do is replace String with StringBuilder in code similar to the above example.

Immutable strings – blessing or curse?

Strings in the .NET framework are immutable – meaning that once they are created they can not be changed. It is a design decision from the .NET framework designers, that allows for a lot of optimizations, but also cost performance under certain circumstances.
This is the main reason the String concatenation from before is so slow. Every time the strings are concatenated, a new String is created, and the old one is left for the garbage collector. At least a thousand strings of increasing size are created, copied and garbage collected for no good reason. It is amazingly ineffective.

StringBuilder – definitely a blessing!

The StringBuilder is the thing to use, when handling and manipulating large strings. It holds the string in an internal array that it grows as needed. This enables a very fast append that only rarely allocates anything new. In my test the StringBuilder initially had a capacity of 64 bytes, and grew to double size whenever needed, but implementations may vary.
This behaviour means that you can optimize performance even further by initializing the StringBuilder to a size that is slightly larger than what you expect the final string to be – thereby removing the need to ever re-allocate.

A word or two about String.Format()

I always assumed that using String.Format() to splice strings with variables was the fastest way of doing it. Tests show, however, that it is not…
I have made test of 4 different ways of accomplishing the same thing:

//using string
string x = "Test of string performance." + 1 + 2 + "hello";
string x = string.Format("Test of string performance.{0}{1}{2}", 1, 2, "hello");

//using StringBuilder
sb.Append("Test of string performance.").Append(1).Append(2).Append("hello");
sb.AppendFormat("Test of string performance.{0}{1}{2}", 1, 2, "hello");

The results are similar for both the String and StringBuilder. Using the +operator or chained appends is roughly twice as fast as using the Format() method. This came as a bit of a surprise to me.