为什么StringBuilder比字符串连接慢?

Jun*_*r M 10 c# stringbuilder string-concatenation

StringBuilder与+连接相比,为什么速度较慢? StringBuilder是为了避免额外的对象创建,但为什么它会惩罚性能?

    static void Main(string[] args)
    {
        int max = 1000000;
        for (int times = 0; times < 5; times++)
        {
            Console.WriteLine("\ntime: {0}", (times+1).ToString());
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < max; i++)
            {
                string msg = "Your total is ";
                msg += "$500 ";
                msg += DateTime.Now;
            }
            sw.Stop();
            Console.WriteLine("String +\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));

            sw = Stopwatch.StartNew();
            for (int j = 0; j < max; j++)
            {
                StringBuilder msg = new StringBuilder();
                msg.Append("Your total is ");
                msg.Append("$500 ");
                msg.Append(DateTime.Now);
            }
            sw.Stop();
            Console.WriteLine("StringBuilder\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));
        }
        Console.Read();
    }
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

编辑:按建议移出范围变量:

在此输入图像描述

seh*_*ehe 15

更改以便不会一直实例化StringBuilder,而是.Clear():

time: 1
String +    :   3348ms
StringBuilder   :   3151ms

time: 2
String +    :   3346ms
StringBuilder   :   3050ms
Run Code Online (Sandbox Code Playgroud)

等等

请注意,这仍然测试完全相同的功能,但尝试更智能地重用资源.

代码:(也住在http://ideone.com/YuaqY)

using System;
using System.Text;
using System.Diagnostics;

public class Program
{
    static void Main(string[] args)
    {
        int max = 1000000;
        for (int times = 0; times < 5; times++)
        {
            {
                Console.WriteLine("\ntime: {0}", (times+1).ToString());
                Stopwatch sw = Stopwatch.StartNew();
                for (int i = 0; i < max; i++)
                {
                    string msg = "Your total is ";
                    msg += "$500 ";
                    msg += DateTime.Now;
                }
                sw.Stop();
                Console.WriteLine("String +\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));
            }

            {
                Stopwatch sw = Stopwatch.StartNew();
                StringBuilder msg = new StringBuilder();
                for (int j = 0; j < max; j++)
                {
                    msg.Clear();
                    msg.Append("Your total is ");
                    msg.Append("$500 ");
                    msg.Append(DateTime.Now);
                }
                sw.Stop();
                Console.WriteLine("StringBuilder\t: {0}ms", ((int)sw.ElapsedMilliseconds).ToString().PadLeft(6));
            }
        }
        Console.Read();
    }
}
Run Code Online (Sandbox Code Playgroud)


Nul*_*ion 6

您正在为StringBuilder每次迭代创建一个新实例,这会产生一些开销.既然你没有将它用于它实际意图做的事情(即:构建大字符串,否则需要许多字符串连接操作),看到比串联更糟糕的性能并不奇怪.

更常见的比较/用法StringBuilder是:

string msg = "";
for (int i = 0; i < max; i++)
{
    msg += "Your total is ";
    msg += "$500 ";
    msg += DateTime.Now;
}

StringBuilder msg_sb = new StringBuilder();
for (int j = 0; j < max; j++)
{
    msg_sb.Append("Your total is ");
    msg_sb.Append("$500 ");
    msg_sb.Append(DateTime.Now);
}
Run Code Online (Sandbox Code Playgroud)

有了这个,你会发现StringBuilder和连接之间存在显着的性能差异.而"重要"是指数量级,而不是您在示例中观察到的~10%的差异.

由于StringBuilder不需要构建大量的中间字符串而不会被丢弃,因此可以获得更好的性能.这就是它的意思.对于较小的字符串,最好使用字符串连接以简化和清晰.

  • 不过,你正在衡量一些完全不同的东西 (2认同)
  • @JuniorMayhé这是正确的答案.像你的例子一样在同一个循环中使用StringBuilder和连接并不能说明整个故事,因为StringBuilder必须等待连接发生.字符串越大,StringBuilder就越快. (2认同)