Concatenation Performance

Search

 by Remas Wojciechowski

July 9th, 2002

In most .NET performance articles you will read the tip to use the StringBuilder class for string concatenation. In this article you will learn whether and when this statement is valid.

Introduction

Take any article dealing with performance issues in .NET applications and in most cases you will read that it is advisable to use the StringBuilder class (namespace: System.Text) for string concatenations. However, regardless of all advantages the StringBuilder class has, from the programmer's perspective it is less comfortable than operator (+) concatenation (be it only that you need to create a new instance of that class). In that context, the question arises whether or not it is always necessary to use the StringBuilder. The intuition is that for only few concatenation statements it shouldn't matter. I decided to find out if the intuition is right and performed a series of tests to that end.

Methodology

In the performance test two contatenation methods were analysed: operator (+) concatenation and StringBuilder concatenation. In order to simulate different real-world scenarios, for every concatenation method

  • a different number of concatenations
  • of different-length strings
were analyzed. The tests were performed by means of a console application on a Dell Latitude C500 Notebook with 384MB RAM. The number of concatenations was based on the powers 0-12 of 2 (1, 2, 4, 8, ..., 4096). For each number of concatenations three string lenghts were used (10, 100 and 1000). One test consisted of all possible combinations of the two parameters mentioned. Five such tests were performed and averages computed.

Below is the source code of the console application used for the test. By changing the first four variables, you can adapt the string lengts and iteration steps to your needs.

Code for the performance tests
using System;
using System.Text;
using System.IO;
namespace PerformanceTests
{
  class Concatenation
  {
    private static int IterationsMaxPower = 12;
    private static int IterationsPowerBase = 2;
    private static int StringLenMaxPower = 3;
    private static int StringLenPowerBase = 10;
    [STAThread]
    static void Main(string[] args)
    {
      CommaSeparated();
    }
    private static void CommaSeparated()
    {
      int IterationsCount;
      string StrToConcatenate = String.Empty;
      string Buffer;
      DateTime start;
      DateTime end;
      TimeSpan DurationPlus = TimeSpan.Zero;
      TimeSpan DurationStringBuilder = TimeSpan.Zero;
      Console.WriteLine("Number of Iterations,String Length,Duration Plus Method [ticks],Duration StringBuilder Method [ticks]");
      for (int IterationsPower = 0; IterationsPower <= IterationsMaxPower; IterationsPower++)
      {
        IterationsCount = (int) Math.Pow((double) IterationsPowerBase, (double) IterationsPower);
        for (int StringLenPower = 0; StringLenPower <= StringLenMaxPower; StringLenPower++)
        {
          Buffer = String.Empty;
          StrToConcatenate = new String('#', (int) Math.Pow((double) StringLenPowerBase, (double) StringLenPower));
          // + Concatenation
          // Timer on
          start = DateTime.Now;
          for (int Iteration = 1; Iteration <= IterationsCount; Iteration++)
          {
            Buffer += StrToConcatenate;
          }
          // Timer off
          end = DateTime.Now;
          DurationPlus = end - start;
          Buffer = String.Empty;
          // StringBuilder Concatenation
          // Timer on
          start = DateTime.Now;
          StringBuilder sb = new StringBuilder(IterationsCount);
          for (int Iteration = 1; Iteration <= IterationsCount; Iteration++)
          {
            sb.Append(StrToConcatenate);
          }
          Buffer = sb.ToString();
          // Timer off
          end = DateTime.Now;
          DurationStringBuilder = end - start;
          Console.WriteLine("{0},{1},{2},{3}", IterationsCount, StrToConcatenate.Length, DurationPlus.Ticks, DurationStringBuilder.Ticks);
        }
      }
    }
  }
}

Results

The table below summarizes the results of the performance tests. Each figure is an average of the five tests (see Methodology).

# Iterations String Length Duration
Plus [ticks] StringBuilder
[ticks]
1 1 0.0 0.0
1 10 0.0 0.0
1 100 0.0 0.0
1 1000 0.0 0.0
2 1 0.0 0.0
2 10 0.0 0.0
2 100 0.0 0.0
2 1000 0.0 0.0
4 1 0.0 0.0
4 10 0.0 0.0
4 100 0.0 0.0
4 1000 0.0 0.0
8 1 0.0 0.0
8 10 0.0 0.0
8 100 0.0 0.0
8 1000 40057.6 0.0
16 1 0.0 0.0
16 10 0.0 0.0
16 100 0.0 0.0
16 1000 40057.6 0.0
32 1 0.0 0.0
32 10 0.0 0.0
32 100 20028.8 0.0
32 1000 80115.2 0.0
64 1 20028.8 0.0
64 10 0.0 0.0
64 100 0.0 0.0
64 1000 380547.2 20028.8
128 1 0.0 0.0
128 10 0.0 0.0
128 100 100144 0.0
128 1000 1782563.2 40057.6
256 1 20028.8 0.0
256 10 20028.8 0.0
256 100 480691.2 0.0
256 1000 7691059.2 100144
512 1 20028.8 0.0
512 10 120172.8 20028.8
512 100 2223196.8 0.0
512 1000 32026051.2 200288
1024 1 100144 0.0
1024 10 600864 0.0
1024 100 10595235.2 40057.6
1024 1000 127383168 480691.2
2048 1 220316.8 0.0
2048 10 2703888 40057.6
2048 100 47908889.6 60086.4
2048 1000 506027632 881267.2
4096 1 861238.4 20028.8
4096 10 13739756.8 20028.8
4096 100 202250822.4 180259.2
4096 1000 1992705370 1782563.2

Note: A tick is equal to 100 nanoseconds. Anotherwords, one second equals 10 million ticks. E.g., concatenating a 100-character string 2048 times took 4.7 seconds with the operator (+) methods whereas it took 0.002 second with the StringBuilder method.

Findings

  1. Up to four iterations the concatenation method is irrelevant. This applies for 1-character strings as well for 1000-character strings.
  2. For short strings (1 to 10 characters) and up to 128 iterations the concatenation method is irrelevant.
  3. The longer the string to concatenate, the greater the relative advantage of the StringBuilder method over the operator (+) method. With growing number of iterations for the same string length, the relative advantage of the StringBuilder method grows too. E.g., concatenating a 1000-character string 128 times with the operator (+) method takes 44 times more time than with the StringBuilder method; concatenating the same string 4096 times with the operator (+) method is 1118 times longer than with the StringBuilder method. At the same time, the StringBuilder method is "only" 43 times faster than the operator (+) method when concatenating 1-character strings 4096 times.

If you have any comments, please feel free to air them (Feedback button).