I couldn't find advantage of StringBuilder in .NET 2.0

I have written a small application to test differet way of appending strings

Method 1: Use + operator. Like s = s + " " + str1 + " " + str2 + " " + str3 + " " + str4 + " " + str5

Method 2: Using String.Join. Like s = String.Join(" ", new string [] {s, str1, str2, str3, str4, str5});

Method 3: Using String.Format. Like s = String.Format("{0} {1} {2} {3} {4} {5}", s, str1,str2,str3,str4,str5);

Method 4: Using StringBuilder.

Here is the tick time I got for 5000 iteration:

Method 1: 19438310752
Method 2: 19796152256
Method 3: 48454067568
Method 4: 24874657960

At my surprise the plus operator was faster than StringBuilder method. I am pasting my code here. It would be great anybody can do similar tests and share experiences or check if there is any bug in my code. Here was my code:

using System;
using System.Diagnostics;
using System.Text;
//using System.Threading;

class MySample{

static string test = "abcdefghijklmnopqrstuvwxyz";
static Random rand = new Random();

static string normalAppendTest()
{
string s = "";
for (int i=0; i < 5000; i++)
{
string str1, str2, str3, str4, str5;
str1 = test.Substring(rand.Next(5),20);
str2 = test.Substring(rand.Next(5),20);
str3 = test.Substring(rand.Next(5),20);
str4 = test.Substring(rand.Next(5),20);
str5 = test.Substring(rand.Next(5),20);
s = s + " " + str1 + " " + str2 + " " + str3 + " " + str4 + " " + str5;
}
return s;
}
static string joinAppendTest()
{
string s = "";
for (int i=0; i < 5000; i++)
{
string str1, str2, str3, str4, str5;
str1 = test.Substring(rand.Next(5),20);
str2 = test.Substring(rand.Next(5),20);
str3 = test.Substring(rand.Next(5),20);
str4 = test.Substring(rand.Next(5),20);
str5 = test.Substring(rand.Next(5),20);
s = String.Join(" ", new string[] {s, str1,str2,str3,str4,str5});
}
return s;
}
static string formatAppendTest()
{
string s = "";
for (int i=0; i < 5000; i++)
{
string str1, str2, str3, str4, str5;
str1 = test.Substring(rand.Next(5),20);
str2 = test.Substring(rand.Next(5),20);
str3 = test.Substring(rand.Next(5),20);
str4 = test.Substring(rand.Next(5),20);
str5 = test.Substring(rand.Next(5),20);
s = String.Format("{0} {1} {2} {3} {4} {5}", s, str1,str2,str3,str4,str5);
}
return s;
}

static string sbAppendTest()
{

string str = "";
for (int i=0; i < 5000; i++)
{
string str1, str2, str3, str4, str5;
str1 = test.Substring(rand.Next(5),20);
str2 = test.Substring(rand.Next(5),20);
str3 = test.Substring(rand.Next(5),20);
str4 = test.Substring(rand.Next(5),20);
str5 = test.Substring(rand.Next(5),20);
StringBuilder sb = new StringBuilder(str);
sb.Append(" ");
sb.Append(str1);
sb.Append(" ");
sb.Append(str2);
sb.Append(" ");
sb.Append(str3);
sb.Append(" ");
sb.Append(str4);
sb.Append(" ");
sb.Append(str5);
str = sb.ToString();

}
return str;
}

public static void Main(string [] args){


string str;
Stopwatch st = Stopwatch.StartNew();
str = normalAppendTest();
st.Stop();
Console.WriteLine("{0}\t{1}", st.ElapsedTicks.ToString(), str.Length.ToString());


st = Stopwatch.StartNew();
str = joinAppendTest();
st.Stop();
Console.WriteLine("{0}\t{1}", st.ElapsedTicks.ToString(), str.Length.ToString());

st = Stopwatch.StartNew();
str = formatAppendTest();
st.Stop();
Console.WriteLine("{0}\t{1}", st.ElapsedTicks.ToString(), str.Length.ToString());

st = Stopwatch.StartNew();
str = sbAppendTest();
st.Stop();
Console.WriteLine("{0}\t{1}", st.ElapsedTicks.ToString(), str.Length.ToString());
}
}



Answer this question

I couldn't find advantage of StringBuilder in .NET 2.0

  • ralfg

    Can I just provide my opinion here. If you are concatenating strings only to output them to the screen via Console.WriteLine or MessageBox.Show, then it really isn't going to matter which is faster as it's not going to provide a noticeable benefit. Just choose the one that you prefer, Truthfully, I use String.Format (it actually uses a StringBuilder underneath) for error messages because the strings are usually pulled from resources with embedded formatting characters.

  • Julian12

    My results with your code:

    21402812 525000

    20926371 525000

    51609507 525000

    25218750 525000



  • egank

    As Dreadjr said nobody ever said StringBuilder was the fastest way to build strings. StringBuilder's benefit is in how it manages memory. Since strings are immutable in .NET once you create a string is exists until it is released from memory. If you change the string you get a new instance. So if you were to create an empty string and then concatenate to it 10 times you'd have 10 or 11 copies of the string in memory.

    You should use StringBuilder when you are building arbitrary strings in piece-meal fashion. In C# calls to string + string +... are internally converter to a call to String.Concat. For up to 4 string values each one is pushed on the stack and then String.Concat is called. More than 4 string values results in a temporary string array being created, the elements being moved to the string array and then String.Concat called. Just to be complete you should avoid calling String.Format whenever possible (even if you have objects other than strings to convert) because the performance at runtime is high because of the string parsing. Honestly you'd figure the compiler could do a compile-time parse of the string and replace it with an optimized expression (like regular expressions) but it doesn't.

    So in a nutshell you should use StringBuilder to build arbitrary strings to conserve memory usage. For fixed strings you can use the + operator for cleanliness but you could also use String.Concat.

    Just my opinion,
    Michael Taylor - 6/21/06


  • Igor Rosenberg

    Though StringBuilder is faster in the rearranged code but I am not sure whether it represents the common scenario. The scenario I am trying to simulate is appending a small number of strings in many places of of the code. For example:

    Console.WriteLine ("You got an error in your application " + applicationName + " at line " + lineNumber);

    So the expression needs to evalate to a string before it ends. It can't keep adding strings and generate the final string afterwards. But the rearranged code, StringBuilder is not generating string inside the loop.

    But I am perplexed why StringBuilder is slower in the original code. It was doing the same amount of operation as + operator. Does C# do optimization like deferred evaluation when appending strings


  • Info_Tech

    With a rearrangement of the call to constructor and to ToString()

     

      static string sbAppendTest() {

     

        string str = "";

        StringBuilder sb = new StringBuilder( str, 0, 0, 525001 );

        for ( int i = 0; i < 5000; i++ ) {

           string str1, str2, str3, str4, str5;

           str1 = test.Substring( rand.Next( 5 ), 20 );

           str2 = test.Substring( rand.Next( 5 ), 20 );

           str3 = test.Substring( rand.Next( 5 ), 20 );

           str4 = test.Substring( rand.Next( 5 ), 20 );

           str5 = test.Substring( rand.Next( 5 ), 20 );

           sb.Append( " " );

           sb.Append( str1 );

           sb.Append( " " );

           sb.Append( str2 );

           sb.Append( " " );

           sb.Append( str3 );

           sb.Append( " " );

           sb.Append( str4 );

           sb.Append( " " );

           sb.Append( str5 );

        }

        return sb.ToString();

      }

     

    I get this kind of performance:

    36785    525000

     

    When I omit the string capacity argument to the constructor, I get this:

    56840    525000



  • CharlieWasAnAngel

    For some more benchmark results comparing "+=" with StringBuilder, see http://www.heikniemi.net/hc/archives/000124.htm
  • RakeshGupta

    a string is immutable, and StringBuilder is mutable. Check out some of the differences here. This will lead you to the anwser... A StringBuilder object will not be faster in the above example, concatenating 4 strings together. StringBuilder is more usStringBuilder beats strings for 10+ concatenations in every practical situation. The performance depends on the size of the strings you are concatenating also.


  • I couldn't find advantage of StringBuilder in .NET 2.0