简体   繁体   中英

StringBuilder performance in C#?

I have a StringBuilder object where I am adding some strings like follows:

I want to know which one is better approach here, first one is this:

StringBuilder sb = new StringBuilder();
sb.Append("Hello" + "How" + "are" + "you");

and the second one is:

StringBuilder sb = new StringBuilder();
sb.Append("Hello").Append("How").Append("are").Append("you");

In your current example, the string literals:

"Hello" + "How" + "are" + "you"

Will be compiled into one constant string literal by the compiler, so it is technically faster than:

sb.Append("Hello").Append("How").Append("are").Append("you");

However, were you to use string variables:

sb.Append(s1 + s2 + s3 + s4);

Then the latter would be faster as the former could potentially create a series of strings (because of the concatenation) before passing the final string into the Append method, whereas the latter would avoid the extra string creations (but trades off extra method calls and internal buffer resizing).

Update: For further clarity, in this exact situation where there are only 4 items being concatenated, the compiler will emit a call to String.Concat(string, string, string, string) , which knowing the length and number of strings will be more efficient than StringBuilder .

The first will be more efficient. The compiler will convert it to the following single call:

StringBuilder sb = new StringBuilder();
sb.Append("HelloHowareyou");

Measuring the performance

The best way to know which is faster is to measure it. I'll get straight to the point: here are the results (smaller times means faster):

sb.Append("Hello" + "How" + "are" + "you")                  : 11.428s
sb.Append("Hello").Append("How").Append("are").Append("you"): 15.314s
sb.Append(a + b + c + d)                                    : 21.970s
sb.Append(a).Append(b).Append(c).Append(d)                  : 15.529s

The number given is the number of seconds to perform the operation 100 million times in a tight loop.

Conclusions

  • The fastest is using string literals and + .
  • But if you have variables, using Append is faster than + . The first version is slower because of an extra call to String.Concat .

In case you want to test this yourself, here's the program I used to get the above timings:

using System;
using System.Text;

public class Program
{
    public static void Main()
    {
        DateTime start, end;
        int numberOfIterations = 100000000;
        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Hello" + "How" + "are" + "you");
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(\"Hello\" + \"How\" + \"are\" + \"you\")", start, end);

        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Hello").Append("How").Append("are").Append("you");
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(\"Hello\").Append(\"How\").Append(\"are\").Append(\"you\")", start, end);

        string a = "Hello";
        string b = "How";
        string c = "are";
        string d = "you";

        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(a + b + c + d);
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(a + b + c + d)", start, end);

        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(a).Append(b).Append(c).Append(d);
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(a).Append(b).Append(c).Append(d)", start, end);

        Console.ReadLine();
    }

    private static void DisplayResult(string name, DateTime start, DateTime end)
    {
        Console.WriteLine("{0,-60}: {1,6:0.000}s", name, (end - start).TotalSeconds);
    }
}

String constants will be concatenated at compile time by the compiler. If you are concatenating no more than four string expressions, the compiler will emit a call to String.Concat

s + t + u + v ==> String.Concat(s, t, u, v)

This performs faster than StringBuilder , as StringBuilder might have to resize its internal buffer, while Concat can calculate the total resulting length in advance. If you know the maximum length of the resulting string in advance, however, you can initialize the StringBuilder by specifying an initial working buffer size

var sb = new StringBuilder(initialBufferSize);

StringBuilder is often used in a loop and other dynamic scenarios and performs faster than s += t in such cases.

In the first case the compiler will construct a single string, so you'll only call Append once. However, I doubt this will make much of a difference. What did your measurements show?

The second one is the better approach. Strings are immutable meaning that when you use sb.Append("Hello" + "How" + "Are" + "You") you are creating multiple copies of the string

eg

"Hello"

then

"HelloHow"

then

"HelloHowAre"

etc.

The second piece of code is much more performant

edit: Of course this doesn't take into consideration compiler optimisations, but it's best to use the class as intended

Ok as people have pointed out since these are literals the compiler takes care of optimising these operations away - but my point is that doing string concatenation is something that StringBuilder tries to avoid

For instance, looping several times as such:

var someString = "";

foreach (var s in someListOfStrings) 
{
    someString += s;
}

Is not as good as doing:

var sb = new StringBuilder();

foreach(var s in someListOfStrings)
{
    sb.Append(s);
}

sb.ToString();

As this will likely be much quicker since, as I said before, strings are immutable

I assumed the OP was talking about using concatenation in general since

sb.Append("Hello" + "How");

Seems completely pointless when

sb.Append("HelloHow");

Would be more logical...?

It seems to me that in the OPs mind, the placeholder text would eventually become a shedload of variables...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM