StringBuilder vs String Concatenation

,Concurrency Visualizer Showing Large Number of Cross Core Context Switches for String Concatenation


Concurrency Visualizer Showing Large Number of Cross-Core Context Switches for String Concatenation

.StringBuilder vs String Concatenation



"This video compares the StringBuilder class against string concatenation using Visual Studio code profiling, the Concurrency Visualizer and the Performance Monitor to measure runtimes, memory allocations, garbage collection, and cross-core context switches."

Two code sections are run under the Visual Studio 2012 Performance Wizard and Concurrency Visualizer. In addition, the first and second generation garbage collection is monitored using the Performance Monitor.

 
00:00


The Demonstration

The two code segments used in this demonstration are:

  1. StringBuilder Class - Append to a string in a loop.

    A StringBuilder object is used in a loop to add one character at a time to create a string consisting of 2E+7 characters. The StringBuilder object is mutable and uses a buffer to expand the number of characters in the string.

    • The StringBuilder code is:
      • StringBuilder sb1 = new StringBuilder(null);
        for (int i = 0; i < 2E7; i++)
        {
            sb1.Append('X');
        }
        string s2 = sb1.ToString();

  2. String Concatenation - Concatenate to end of string in a loop.

    A String object is used in a loop to add one character at a time to create a string consisting of 2E+5 characters. The String object is immutable and creates a new string on the heap each time a character is added.

    • The String code is:
      • string s1 = string.Empty;
        for (int i = 0; i < 2E5; i++)
        {
            s1 += 'X';
        }

Results

The results for the code comparison are:

  1. The StringBuilder code completed in 0.775 seconds and allocated 78.4 MBytes to create a string consisting of 2E+7 characters.

  2. The String Concatenation code completed in 25.3 seconds and allocated 39.9 GBytes to create a string consisting of 2E+5 characters.

  3. For the String Concatenation code, the garbage collection performance counters indicate a large amount of generation 1 and generation 2 garbage collection. Generation 2 garbage has survived the longest and is the most expensive to collect. The String Concatenation code received the DA0022: High rate of Gen 2 garbage collections warning message. MSDN's information about the DA0022 message states:

    Well-behaved .NET Framework applications will have more than 5 times as many generation 1 garbage collections as generation 2 collections. (A 10x factor is probably ideal.)

,First and Second Garbage Collection


First and Second Garbage Collection for StringBuilder (left) and String Concatenation


  1. Visual Studio's comparison of the code profiles showed the String Concatenation code allocated much more storage space for the String and Char data types. The String allocation ratio was approximately 1:100 Bytes and the Char ratio was 0:2.3 MBytes. The comparison report also showed the StringBuilder code made much for frequent use of a Char array in creating the strings.
,Memory Allocation Comparisons


Memory Allocation Comparisons for StringBuilder (baseline) vs String Concatenation

  1. Visual Studio's Concurrency Visualizer showed the String Concatenation code performed a much higher number of context switches. The number of cross-core context switches was especially high with 569 as compared to 59 for the StringBuilder code.
,Context Switching Comparison for StringBuilder vs String Concatenation


Context Switching Comparison for StringBuilder (top) vs String Concatenation


  1. Visual Studio's Concurrency Visualizer showed the main thread for the String Concatenation code was considerably more fragmented. The main thread for the StringBuilder code showed the process was performing initial memory management activities in preparation for building the strings, where the String Concatenation code starting building the string immediately. The CPU utilization graphs also showed the StringBuilder code utilized the CPU more heavily during the processes, with especially heavy amounts of activity at the beginning and the end of the process.
,Thread Utilization Comparison for StringBuilder vs String Concatenation


Thread Utilization Comparison for StringBuilder (top) vs String Concatenation


C# Code Used in the Demonstration Video


namespace MutableStrings
{
    class Program
    {
        static void Main(string[] args)
        {

         #region StringBuilder
            Console.WriteLine("StringBuilder running ...");
            StringBuilder sb1 = new StringBuilder(null);
            for (int i = 0; i < 2E7; i++)
            {
                sb1.Append('X');
            }
            string s2 = sb1.ToString();
            Console.WriteLine("Length of s2 is: {0}", s2.Length.ToString("E"));
         #endregion StringBuilder

         #region String Concatenation
            Console.WriteLine("String concat running ...");
            string s1 = string.Empty;
            for (int i = 0; i < 2E5; i++)
            {
                s1 += 'X';
            }
            Console.WriteLine("Length of s1 is: {0}", s1.Length.ToString("E"));
         #endregion String Concatenation
        }
    }
}



Reference Articles


Top