none
GC and String Concatenation vs StringBuilder RRS feed

  • Question

  • I have an ASP.NET application that is getting very high CPU rates with just 500 connected users, so I searched and found the following ms article.  http://support.microsoft.com/kb/307340  Although my scenario is slightly different in that I create lots of little strings instead of 1 very large string, so I wrote the following console app to test the performance difference.

     Imports System.Text
    Module Module1
     Sub Main()
     Dim from As DateTime
     Const dur As Integer = 10000000
     from = Now
     concatSTR(dur)
     Display("String", Now - from)
     from = Now
     concatSB1(dur)
     Display("StringBuilder1", Now - from)
     from = Now
     concatSB2(dur)
     Display("StringBuilder2", Now - from)
     Console.Write("Press a key")
     Console.ReadKey()
     End Sub
     Sub Display(ByVal txt As String, ByVal TS As TimeSpan)
     Console.WriteLine(String.Format("{0,-15} {1:D2}:{2:D2}:{3:D}", txt, TS.Minutes, TS.Seconds, TS.Milliseconds))
     End Sub
     Sub concatSTR(ByVal cnt As Integer)
     Dim str As String
     For i As Integer = 1 To cnt
      str = "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz "
     Next
     End Sub
     Sub concatSB1(ByVal cnt As Integer)
     Dim SB As StringBuilder
     For i As Integer = 1 To cnt
      SB = New StringBuilder(1000)
      For x As Integer = 1 To 10
      SB.Append("abcdefghijklmnopqrstuvwxyz ")
      Next
      SB = Nothing
     Next
     End Sub
     Sub concatSB2(ByVal cnt As Integer)
     Dim SB As New StringBuilder(1000)
     For i As Integer = 1 To cnt
      SB.Length = 0
      For x As Integer = 1 To 10
      SB.Append("abcdefghijklmnopqrstuvwxyz ")
      Next
     Next
     SB = Nothing
     End Sub
    End Module
     
    The results were not what I expected.

    String              00:00:47
    StringBuilder1  00:05:871
    StringBuilder2  00:02:967

    So what exactly are the disadvantages of using string concatenation ?  

    And, can anyone else think of any other reasons for high CPU on just 500 users, or what I could look for (I don't have access to the machines nor do I have any bulk testing software).

     

     

    Tuesday, January 25, 2011 11:03 AM

Answers

  • I don't know exactly what your trying but:

    Sub concatSTR(ByVal cnt As Integer)
     Dim str As String
     For i As Integer = 1 To cnt
      str = "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz "
     Next
     End Sub

    Doesn't contain any concatenation during runtime!! There is only one assignment happening 'cnt' times!

    The compiler makes of the multiple lines one string.

    • Proposed as answer by rob_v_ Tuesday, January 25, 2011 4:45 PM
    • Marked as answer by eryang Monday, February 7, 2011 2:57 AM
    Tuesday, January 25, 2011 4:10 PM
  • Hi Adrean Parker, The compiler will do the same thing because at compile time, compiler exactly knows (in your case variable a is known at compile time) what the variable contains. But in case of a string variable passed in a function parameter will make things different.

    Muhammad Nadeem BrickRed Technology India
    • Marked as answer by eryang Monday, February 7, 2011 2:57 AM
    Wednesday, January 26, 2011 2:54 PM

All replies

  • Hi Adrian,

     

    Please follow this nice link to understand and troubleshoot the memory issue:

    http://msdn.microsoft.com/en-us/magazine/dd882521.aspx

    http://msdn.microsoft.com/en-us/magazine/cc163528.aspx

     

    If this doesn't help then you have to take a look by using CLR Profiler.

    I would suggest you to use StringBuilder it is fast  and less burden on GC when heavily used in both single or multi threaded environment.

    Hope it helps you if now, Can you please paste your code here so that we can investigate it.

    Thanks,

    Nadeem


    Muhammad Nadeem BrickRed Technology India
    Tuesday, January 25, 2011 12:07 PM
  • Thanks for the links, I'll have a look in a minute.  

    The point of the code above is that StringBuilder is running significantly slower.

    Tuesday, January 25, 2011 3:22 PM
  • Thanks for the links, I'll have a look in a minute.  

    The point of the code above is that StringBuilder is running significantly slower.

    Hello Adrian,

    I tried your test, confirmed your results and started to wonder why I also replaced string concatenation by StringBuilder, then I realized that though you have main loop 10000000x, in fact you create new StringBuilder for each 10 strings - string concatenation for small number of strings is faster than StringBuilder (due to SB overhead and/or copy of small strings is fast).

    if you modify your test to concatenate to 1 string and 1 SB then you will see remarkable difference, e.g. I had to change dur to 10000 only:

    Const dur As Integer = 10000

    String               00:28:343
    StringBuilder2  00:00:15

      Sub concatSTR(ByVal cnt As Integer)
        Dim str As String = String.Empty
        For i As Integer = 1 To cnt
          str += "abcdefghijklmnopqrstuvwxyz " + _
            "abcdefghijklmnopqrstuvwxyz " + _
            "abcdefghijklmnopqrstuvwxyz " + _
            "abcdefghijklmnopqrstuvwxyz " + _
            "abcdefghijklmnopqrstuvwxyz " + _
            "abcdefghijklmnopqrstuvwxyz " + _
            "abcdefghijklmnopqrstuvwxyz " + _
            "abcdefghijklmnopqrstuvwxyz " + _
            "abcdefghijklmnopqrstuvwxyz " + _
            "abcdefghijklmnopqrstuvwxyz "
        Next
      End Sub
    
      Sub concatSB2(ByVal cnt As Integer)
        Dim SB As New StringBuilder(1000 * cnt)
        For i As Integer = 1 To cnt
          'SB.Length = 0
          For x As Integer = 1 To 10
            SB.Append("abcdefghijklmnopqrstuvwxyz ")
          Next
        Next
        SB = Nothing
      End Sub
    
    rob

    Tuesday, January 25, 2011 3:41 PM
  • Yes I know it's faster creating very large strings, but I'm creating a lot of smallish strings.. about 1000 char SQL statements, so am wondering whether using the slower (in my scenario) stringbuilder method will be better as far as GC is concerned.
    Tuesday, January 25, 2011 3:49 PM
  • i'm not an expert but in my opinion surely same number of SBs (that are slower in your case) won't be better than same number of strings re GC - both are Class-es

    rob

    Tuesday, January 25, 2011 4:03 PM
  • I don't know exactly what your trying but:

    Sub concatSTR(ByVal cnt As Integer)
     Dim str As String
     For i As Integer = 1 To cnt
      str = "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz " + _
       "abcdefghijklmnopqrstuvwxyz "
     Next
     End Sub

    Doesn't contain any concatenation during runtime!! There is only one assignment happening 'cnt' times!

    The compiler makes of the multiple lines one string.

    • Proposed as answer by rob_v_ Tuesday, January 25, 2011 4:45 PM
    • Marked as answer by eryang Monday, February 7, 2011 2:57 AM
    Tuesday, January 25, 2011 4:10 PM
  • excellent point boothwine!, so it explains those "unexpected" results :-) with that change in Adrian's test:

        Sub concatSTR(ByVal cnt As Integer)
            Dim str As String
            For i As Integer = 1 To cnt
                str = String.Empty
                For x As Integer = 1 To 10
                    str += "abcdefghijklmnopqrstuvwxyz "
                Next
            Next
        End Sub

    concatSTR took instead of less than 1 sec more than 13 sec..

    String          00:13:328
    StringBuilder2  00:03:531

    Tuesday, January 25, 2011 4:44 PM
  • Gud Catch BoothWin :)

    We missed that first.


    Muhammad Nadeem BrickRed Technology India
    Wednesday, January 26, 2011 12:18 PM
  • Aha ok, that would explain it. Would it do the same with embedding variables in the string addition too or would it then work differently.. eg. dim s as string dim a as string = "some text" s = "this is " + a + " added together"
    Wednesday, January 26, 2011 12:23 PM
  • Hi Adrean Parker, The compiler will do the same thing because at compile time, compiler exactly knows (in your case variable a is known at compile time) what the variable contains. But in case of a string variable passed in a function parameter will make things different.

    Muhammad Nadeem BrickRed Technology India
    • Marked as answer by eryang Monday, February 7, 2011 2:57 AM
    Wednesday, January 26, 2011 2:54 PM