-5

How Much Faster is StringBuilder respect of concat operator + in C# .Net How it work at low level to work faster than concat?

abrfra
  • 634
  • 2
  • 6
  • 24
  • 2
    You could measure it yourself and find out. – John Saunders Mar 20 '14 at 14:43
  • It depends on how many concatenations you are doing. Agree with @JohnSaunders. Test it in your environment and measure for yourself. (Then post your results here). – Jim Wooley Mar 20 '14 at 14:44
  • StringBuilder is faster in part because it uses a buffer rather than allocating a new string from the heap for each operation. – 500 - Internal Server Error Mar 20 '14 at 14:46
  • 2
    Keep in mind that without `StringBuilder` you will be creating new strings, which means new objects, which at some point will be garbage collected. That delay should also be measured for a valid comparison. – C.Evenhuis Mar 20 '14 at 14:49
  • StringBuilder uses char arrays internally so it is much faster than concatenating many strings. However it is slower if you are only concatenating 2 or 3 strings due to the overhead of creating the stringbuilder object. StringBuilder also results in less memory pressure as less small objects are created on the heap than would be by concatenating lots of strings which means that the garbage collector is called less often. – coolblue2000 Mar 20 '14 at 14:50
  • 3
    [C# StringBuilder Performance](http://www.dotnetperls.com/stringbuilder-performance) gives you a nice overview of the performance. – Abbas Mar 20 '14 at 14:51
  • It depends on the machine, on my computer is about 120 times faster, but it's very easy to test, try it yourself. As a side note, as C.Evenhuis already pointed out concatenating creates a lot of intermediate strings. – Alessandro D'Andria Mar 20 '14 at 14:52
  • @AlessandroD'Andria It's not really meaningful to apply a factor like that. Both methods are preferable in different contexts. Depending on which situation you test, you'll see different results. – Servy Mar 20 '14 at 15:02
  • @Servy yes i know, it's simply some orientative info, in general the issue (at least to me) with concatenation is the temp strings created. Eric Lippert has a nice [article](http://ericlippert.com/2013/06/17/string-concatenation-behind-the-scenes-part-one/) on strings concatenation. – Alessandro D'Andria Mar 20 '14 at 15:07

3 Answers3

4

The Microsoft Developer Network has a great comparison:

Although StringBuilder and String both represent sequences of characters, they are implemented differently. String is an immutable type. That is, each operation that appears to modify a String object actually creates a new string.

For example, the call to the String.Concat method in the following C# example appears to change the value of a string variable named value. In fact, the Concat method returns a value object that has a different value and address from the value object that was passed to the method. Note that the example must be compiled using the /unsafe compiler option. For routines that perform extensive string manipulation (such as apps that modify a string numerous times in a loop), modifying a string repeatedly can exact a significant performance penalty. The alternative is to use StringBuilder, which is a mutable string class. Mutability means that once an instance of the class has been created, it can be modified by appending, removing, replacing, or inserting characters. A StringBuilder object maintains a buffer to accommodate expansions to the string. New data is appended to the buffer if room is available; otherwise, a new, larger buffer is allocated, data from the original buffer is copied to the new buffer, and the new data is then appended to the new buffer.

The recommended usage for a String is:

  • When the number of changes that your application will make to a string are quite small. In these instances StringBuilder may offer negligible or no performance improvement over String. (Due to the way the StringBuilder handles its buffer)

  • When you are performing a fix number of concatenation operations, particularly with String literals. The Compiler should combine these into one single operation.

  • When you have to perform extensive search operations while you are building a String. StringBuilder lacks search methods such as IndexOf or StartsWith. You'll have to convert your StringBuilder object to a String for these operations which may negate the performance.

The recommended usage for StringBuilder:

  • When you expect your application to make unknown number of changes to a string at design time (an example would be loops/random number strings).

  • When you expect your application to make significant changes to a string.

So the question really shouldn't be, "Which performs better", it should be "Under which circumstance is one more ideal than another?"

Greg
  • 11,302
  • 2
  • 48
  • 79
1

Just to contrast the other answer, here is an example that shows concatenation is faster by about 20% on my computer.

public static void ConcatTest()
{
    int NumConcatenations = 10000000;

    const string Postfix = "postfix_";

    /** + Operator concatenation **/
    var sw = Stopwatch.StartNew();
    for (int x = 0; x < NumConcatenations; x++)
    {
        var concatResult = string.Empty;

        for (int i = 0; i < 2; i++)
        {
            concatResult += Postfix;
        }
    }
    var plusOperatorTime = sw.ElapsedMilliseconds;

    Console.WriteLine();

    sw.Reset();

    /** StringBuilder concatenation **/
    sw.Start();
    for (int x = 0; x < NumConcatenations; x++)
    {
        var builder = new StringBuilder(string.Empty);
        for (int i = 0; i < 2; i++)
        {
            builder.Append(Postfix);
        }
    }
    var stringBuilderTime = sw.ElapsedMilliseconds;

    Console.WriteLine(
        "Concatenation with + operator took {0} ms, stringbuilder took {1} ms",
        plusOperatorTime,
        stringBuilderTime);

    Console.ReadLine();
}

Are you concatenating the words of a novel into a book or are you concatenating a million firstname lastname pairs into full name? Your usage determines what is faster. Testing your specific implementation is the only way to know for sure.

tonyriddle
  • 388
  • 1
  • 3
  • 12
-1

WOW ... I'm measuring a 100 fold performance difference. Stringbuilder by far faster. Feel free to tell me what's wrong with my code.

On my system: 200ms for + vs 2 ms for stringbuilder.

       static void Main(string[] args)
    {
        int NumConcatenations = 10000;

        const string Postfix = "postfix_";
        var concatResult = string.Empty;

        /** + Operator concatenation **/
        var sw = Stopwatch.StartNew();
        for (int i = 0; i < NumConcatenations; i++)
        {
            concatResult += Postfix;
        }
        var plusOperatorTime = sw.ElapsedMilliseconds;

        Console.WriteLine();

        sw.Reset();

        /** StringBuilder concatenation **/
        var builder = new StringBuilder(string.Empty);
        sw.Start();
        for (int i = 0; i < NumConcatenations; i++)
        {
            builder.Append(Postfix);
        }
        var stringBuilderTime = sw.ElapsedMilliseconds;

        Debug.Assert(concatResult.Length == builder.ToString().Length);

        Console.WriteLine(
            "Concatenation with + operator took {0} ms, stringbuilder took {1} ms",
            plusOperatorTime,
            stringBuilderTime);

        Console.ReadLine();
    }
Jochen van Wylick
  • 5,303
  • 4
  • 42
  • 64
  • To be fair, the StringBuilder class pre-allocates memory and doubles the buffer in memory every time you cross the boundary (if I recall correctly). – Adam Sears Mar 20 '14 at 15:00
  • 1
    You can't just make the global statement that one is better than the other. They are each appropriate in different contexts, and will out perform the other when used appropriately. If one way was just universally better than there would be no need to have two ways. – Servy Mar 20 '14 at 15:00
  • @AdamSears No, it does not (anymore). That is the pre .NET 4.0 implementation. – Servy Mar 20 '14 at 15:00
  • @Servy: Maybe I'm mis-reading the [reference source](http://referencesource.microsoft.com/#mscorlib/system/text/stringbuilder.cs#adf60ee46ebd299f) for StringBuilder? I thought that is what it's doing. Maybe not doubling the buffer, but it definitely is pre-allocating space in advance. – Adam Sears Mar 20 '14 at 18:40
  • @AdamSears It's basically creating a linked list of character arrays, each of which are pulled from all of the appended strings. When you then call `ToString` it creates flattens them all out into a single character array, rather than pre-allocating the space and copying items on every single append. – Servy Mar 20 '14 at 18:42