简体   繁体   English

StringBuilder在C#中的表现?

[英]StringBuilder performance in C#?

I have a StringBuilder object where I am adding some strings like follows: 我有一个StringBuilder对象,我在其中添加如下字符串:

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). 然后后者会更快,因为前者可能会将最终字符串传递给Append方法之前创建一系列字符串(因为连接),而后者将避免额外的字符串创建(但交换额外的方法调用和内部缓冲区大小调整)。

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 . 更新:为了进一步清晰,在这种只有4个项连接的确切情况下,编译器将发出对String.Concat(string, string, string, string)的调用,知道String.Concat(string, string, string, string)的长度和数量会更多比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. 给出的数字是在紧密循环中执行操作1亿次的秒数。

Conclusions 结论

  • The fastest is using string literals and + . 最快的是使用字符串文字和+
  • But if you have variables, using Append is faster than + . 但是如果你有变量,使用Append+更快。 The first version is slower because of an extra call to String.Concat . 由于对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 如果连接不超过四个字符串表达式,编译器将发出对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. 这比StringBuilder执行得更快,因为StringBuilder可能必须调整其内部缓冲区的大小,而Concat可以提前计算总生成长度。 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 但是,如果您事先知道结果字符串的最大长度,则可以通过指定初始工作缓冲区大小来初始化StringBuilder

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. StringBuilder通常用于循环和其他动态场景,并且在这种情况下比s += t执行得更快。

In the first case the compiler will construct a single string, so you'll only call Append once. 在第一种情况下,编译器将构造一个字符串,因此您只需调用一次Append。 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 字符串是不可变的意味着当你使用sb.Append(“Hello”+“How”+“Are”+“You”)时,你正在创建字符串的多个副本

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 好的,因为人们已经指出,因为这些是文字,编译器负责优化这些操作 - 但我的观点是做字符串连接是StringBuilder试图避免的

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 我认为OP一直在谈论使用连接

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... 在我看来,在OP的思想中,占位符文本最终将变成一堆变量......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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