Wednesday, August 5, 2009

Strings and performance

I really cannot stress enough importance of using StringBuilder class for string concatenation. The reason is obvious: PERFORMANCE! I know that most programmers are aware of the possible string concatenations performance problems but somehow this issue is still being overlooked and many make the mistake.The difference in performance between using and not using StringBuilder is HUGE as I'll show in simple demo application. I'm not saying that you should use StringBuilder for every string concatenation, but be very alert when you have loops that do string concatenation. Stop for a minute and think about possible performance issues. How much iteration do you expect your loop to have? If you loop through collection that you expect to get bigger and bigger over time, or a collection that you know nothing about (such as one coming from external system) then using StringBuilder has no alternative. Let's take a look how long does it take to do for example 30 000 string concatenations. by using StringBuilder. Code looks as follows :

class Program
  { 
      static void Main(string[] args) 
      { 
          StringBuilder sb = new StringBuilder(); 
          DateTime start = DateTime.Now;  
          for (int i = 0; i <30000; i++) 
          { 
              sb.Append("some string"); 
          } 
          TimeSpan ts = DateTime.Now - start;  
          Console.WriteLine("Finished!"); 
          Console.WriteLine(ts.TotalSeconds); 
          Console.ReadLine(); 
      } 
}

On my computer it takes exactly 0.15625 seconds which is very very fast.

image

Now let's take a look at same code but without using StringBuilder

 class Program
  { 
      static void Main(string[] args) 
      { 
          string str= string.Empty; 
          DateTime start = DateTime.Now;  
          for (int i = 0; i <30000; i++) 
          { 
              str+= "some string"; 
          } 
          TimeSpan ts = DateTime.Now - start;  
          Console.WriteLine("Finished!"); 
          Console.WriteLine(ts.TotalSeconds); 
          Console.ReadLine(); 
      } 
  }

Without StringBuilder it takes 21.396625 seconds.

image

Difference in performance is very noticeable and benefit of using StringBuilder is obvious. It's worth noting that performance issues are usually not discovered until system has been deployed and used in production, but by that time damage can already be done. That's why string concatenation must be taken with care.

4 comments:

  1. Your loop is rather large. You should try comparing the differences for smaller numbers of concatenations, you might be surprised to find that for a lot of more realistic numbers of iterations (like tens of concatenations, instead of 10 of thousands of concatenations) StringBuilder is slower.

    Herbie

    ReplyDelete
  2. Yes, you are probably right for smaller number of iterations, but StringBuilder does scale better. Sometimes it's not possible to know how big collections are going to be. Imagine an online business that has a separate application which goes through XML files provided by their business partners, extracts data from the files and does some intensive string concatenations. Length of XML files can vary, some partners can provide files with ten of thousands items. I had such situations in mind when writing the post. Thanks for comment:)

    ReplyDelete
  3. Well... I am not very sure if Herbie is correct here.

    To test out if his statement is correct you should run about 1000 tests in loop. The body of loop makes string concatenation 10 times. Otherwise you have too much "noise" from other programs. But I think it is worth to try. :)

    ReplyDelete
  4. Well, I didn't want to blow my own trumpet, but I actually did some tests a few years ago in .Net1.1.

    I wrote the results as a Codeproject article: http://www.codeproject.com/KB/cs/stringperf.aspx

    You could try and see if things have improved in more recent versions of .Net (I haven't got around to it yet).

    My general rule of thumb is: if I don't know exactly how many iterations are going to be required, I use StringBuilder; if I do know how many iterations are required and it's a small(ish) number then I'll just use string +=

    Herbie

    ReplyDelete