You want to find out if your code has this common StringBuilder mistake. Sometimes StringBuilder code has inefficient string appends in it. Optimize StringBuilder code that has this mistake. Here we look at this mistake and see ways you can fix it easily, using the C# programming language.
~~~ StringBuilder mistake and benchmark using C# ~~~ Based on .NET 3.5 SP1. It is faster to avoid concatenating strings inside Append calls. Before, with concat: 1841 ms After, separate Appends: 1154 ms [faster]
First, I have seen code like I show next in the real-world. In fact, some C# code that I installed on this web site for an advertising company made this mistake. Let's look at the mistake first.
=== StringBuilder code with performance problem (C#) ===
static void Test1()
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < _iterations; i++)
{
string extra = i.ToString();
string before = "okay" + extra;
string url = "http://sometest.com/" + extra;
string text = "Some Test" + extra;
string after = "That's Good" + extra;
builder.Append(@"<li style=""float: right; clear: none;
display: block; margin: 0; padding: 0;"">" +
before + @" <a href=""" + url + @""">" + text + "</a> " + after + "</li>");
}
}It declares a StringBuilder. We declare a StringBuilder, which is great for this situation. It uses the plus operator. The five string declarations in the inner loop are not really important to look at—they are just there for the benchmark and because they were there in the code I am fixing. Look at the lines with Append.
It's a mess. I apologize for the syntax mess in the last part of the loop above. You doubtless have a lot of code that looks like this or worse. What this code does is build an HTML string of list elements. It isn't optimal. This is the before code that has a hidden inefficiency. Read on for the improvements we should make.
When you use StringBuilder, don't also use +. The plus operator creates a bunch of temporary strings. Eliminate these for better performance.
=== Faster StringBuilder implementation (C#) ===
static void Test2()
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < _iterations; i++)
{
string extra = i.ToString();
string before = "okay" + extra;
string url = "http://sometest.com/" + extra;
string text = "Some Test" + extra;
string after = "That's Good" + extra;
builder.Append(@"<li style=""float: right; clear: none;
display: block; margin: 0; padding: 0;"">").Append(
before).Append(@" <a href=""").Append(url).Append(@""">").Append(
text).Append("</a> ").Append(after).Append("</li>");
}
}It doesn't use +. We eliminate the plus on the strings, and simply pass the strings directly to Append on StringBuilder. It chains Appends. See my article on the Append methods here. This syntax is the same as calling builder.Append() over and over again, just shorter.
See StringBuilder Append Syntax.
The above figures shows the time for the method to run 1000 iterations in the inner loop 1000 times. The memory usage isn't big here because the StringBuilder doesn't grow too large in each of the 1000 runs.
Here we looked at a common mistake found when using StringBuilder in real-world programs. You should avoid using the + concatenation operator in the same statements as StringBuilder. This can improve performance by 40%. I think the best option is to use the syntax in the final example.