代码之家  ›  专栏  ›  技术社区  ›  johnc

在什么情况下,使用StringBuilder会变得无关紧要或成为一项开销?

  •  16
  • johnc  · 技术社区  · 17 年前

    stringOut=string1+“”string2 StringBuilder的样式连接(在10000x+循环中使用,StringBuilder每次都是新的)只是为了看看在较小的连接中会有什么不同。

    我发现,在性能测试的多次运行中,无论是串联还是StringBuilder,更改的大小都是微不足道的(重复此操作是为了 小的

    StringBuilder对象的“更新”在什么程度上否定了使用StringBuilder对象的好处?

    7 回复  |  直到 17 年前
        1
  •  20
  •   Ed Swangren    17 年前

    我遵循的规则是-

    当编译时连接数未知时,请使用StringBuilder。

    因此,在您的例子中,每个StringBuilder只附加了几次,然后就被丢弃了。这与类似的事情并不完全相同

    string s = String.Empty;
    for (int i = 0; i < 10000; ++i)
    {
        s += "A";
    }
    

    使用StringBuilder将显著提高性能,因为否则您将不断分配新内存。

        2
  •  18
  •   Jon Skeet    17 年前

    我肯定我有另一个答案,我刚刚发布了一个 link to my article 然后是总结,但我们再来一次。

    • 肯定用 StringBuilder 当您在一个非平凡的循环中连接时——特别是当您不确定(在编译时)将通过循环进行多少次迭代时。例如,一次读取一个文件一个字符,使用+=运算符构建一个字符串可能会导致性能下降。

    • 当您可以(易读地)在一条语句中指定需要连接的所有内容时,一定要使用连接运算符。(如果您有一系列的东西要连接,请考虑调用) String.Concat 明确-或 String.Join

    • 不要害怕将文字分解为几个串联的位-结果将是相同的。例如,您可以通过将一个长文本拆分为几行来提高可读性,而不会对性能造成任何损害。

    • 如果您需要连接的中间结果,而不是输入下一次连接迭代, 字符串拼接 如果您不需要(名字+姓氏)字符串用于其他目的(就像我们在创建 Person 对象)。

    • 如果您只需要进行一些连接,并且您真的希望在单独的语句中进行连接,那么走哪条路并不重要。哪种方法更有效将取决于连接的数量、所涉及的字符串大小以及它们连接的顺序。如果您真的认为这段代码是一个性能瓶颈,那么可以从两个方面对其进行评测或基准测试。

        3
  •  6
  •   oefe    17 年前

    有时候值得一看 documentation :

    串联的性能 StringBuilder对象取决于 通常会发生内存分配。A. 字符串连接操作总是 StringBuilder连接操作 StringBuilder对象缓冲区太小 小到可以容纳新数据。 最好是串联 如果字符串数目固定,则执行操作 对象被连接起来。因为 在这种情况下,单个串联 操作甚至可以合并为 StringBuilder对象更适合用于 如果 可以使用任意数量的字符串 串联;例如,如果一个循环 连接随机数目的 用户输入的字符串。

    在您的示例中,每个输出字符串只有一个串联,因此StringBuilder不会为您带来任何好处。如果要添加到,则应使用StringBuilder 一串 多次,例如:

    stringOut = ...
    for(...)
        stringOut += "."
        stringOut += string2
    
        4
  •  2
  •   joel.neely    17 年前

    我的经验法则很简单。

    1. 如果您可以合理地编写一个表达式来生成final,那么使用 + .
    2. 如果不能(由于大小或可变性),则使用StringBuilder。

    根据我的经验,表达方式如下:

    "Id: " + item.id + " name: " + item.name
    

    比以下内容更容易书写和理解:

    StringBuilder sb = new StringBuilder();
    sb.append("Id: ").append(item.id);
    sb.append(" name: ").append(item.name);
    

    sb 上面的表达式应该已经编写好了),并且它的性能同样好(提示:查看编译后的代码以了解原因!)

    另一方面,当需要在时间(程序运行时)或空间(由来自代码不同部分的值组成)上累积字符串时,如果无法将其作为单行表达式写入,则StringBuilder可以避免以下开销(时间和内存波动):

    String s = somethingExpression;
    ...
    s += someOtherExpression;
    ...
    s += yetAnotherExpression;
    ...
    
        5
  •  1
  •   LukeH    17 年前

    从…起 MSDN :

    [T] 他喜欢上弦乐课 如果一个固定的 连接。在这种情况下 单个串联操作 甚至可以合并成一个 由编译器执行的操作。A. StringBuilder对象更适合用于 如果 可以使用任意数量的字符串 连接随机数目的 用户输入的字符串。

    我想答案是“视情况而定”——如果你在一个循环中连接了超过几个迭代,那么StringBuilder几乎总能提供更好的性能,但唯一确定的方法是实际分析。

        6
  •  1
  •   Sean    17 年前

    这方面有一篇有趣的文章在 Coding Horror . Jeff在双核3.5 GHz core 2 Duo上进行了100000次迭代,得到了以下结果:

     Simple Concatenation    - 606 ms
     String.Format           - 665 ms
     string.Concat           - 587 ms
     String.Replace          - 979 ms
     StringBuilder           - 588 ms
    
        7
  •  1
  •   Peter Mortensen Pieter Jan Bonestroo    16 年前

    从…起 Dot Net Perls

    何时使用StringBuilder?

    StringBuilder完全是一种优化,除了内部实现之外,它对string Concat没有任何逻辑上的改进。也就是说,在高性能应用程序和网站中正确使用它是至关重要的。

    有时,使用4次或更少迭代的小循环和简单的字符串Concats是可以的。然而,在边缘情况下,这可能是灾难性的。使用StringBuilder规划边缘案例。

    推荐文章