c# - C#中的字符串操作优化

标签 c# string optimization performance

以下 C# 代码需要 5 分钟才能运行:

int i = 1;
string fraction = "";
while (fraction.Length < 1000000)
{
    fraction += i.ToString();
    i++;
}

像这样“优化它”会导致它在 1.5 秒内运行:

int i = 1;
string fraction = "";
while (fraction.Length < 1000000)
{
    // concatenating strings is much faster for small strings
    string tmp = "";
    for (int j = 0; j < 1000; j++)
    {
        tmp += i.ToString();
        i++;
    }
    fraction += tmp;
}

编辑:有些人建议使用 StringBuilder,这也是一个很好的建议,结果在 0.06 秒时出现:

int i = 1;
StringBuilder fraction = new StringBuilder();
while (fraction.Length < 1000000)
{
    fraction.Append(i);
    i++;
}

寻找 j 的最佳值是另一个话题,但为什么这种不明显的优化效果如此好?此外,在相关主题上,我听说您永远不应该对字符串使用 + 运算符,而应使用 string.Format(),这是真的吗?

最佳答案

我根本没有得到你的结果。在我的盒子上,StringBuilder 轻松获胜。你能发布你的完整测试程序吗?这是我的,具有三个变体 - 您的字符串连接优化、“简单”的 StringBuilder 和具有初始容量的 StringBuilder。我增加了限制,因为它在我的盒子上运行得太快以至于无法有效测量。

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

public class Test
{
    const int Limit = 4000000;

    static void Main()
    {
        Time(Concatenation, "Concat");
        Time(SimpleStringBuilder, "StringBuilder as in post");
        Time(SimpleStringBuilderNoToString, "StringBuilder calling Append(i)");
        Time(CapacityStringBuilder, "StringBuilder with appropriate capacity");
    }

    static void Time(Action action, string name)
    {
        Stopwatch sw = Stopwatch.StartNew();
        action();
        sw.Stop();
        Console.WriteLine("{0}: {1}ms", name, sw.ElapsedMilliseconds);
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

    static void Concatenation()
    {
        int i = 1;
        string fraction = "";
        while (fraction.Length < Limit)
        {
            // concatenating strings is much faster for small strings
            string tmp = "";
            for (int j = 0; j < 1000; j++)
            {
                tmp += i.ToString();
                i++;
            }
            fraction += tmp;            
        }
    }

    static void SimpleStringBuilder()
    {
        int i = 1;
        StringBuilder fraction = new StringBuilder();
        while (fraction.Length < Limit)
        {
            fraction.Append(i.ToString());
            i++;
        }
    }

    static void SimpleStringBuilderNoToString()
    {
        int i = 1;
        StringBuilder fraction = new StringBuilder();
        while (fraction.Length < Limit)
        {
            fraction.Append(i);
            i++;
        }
    }

    static void CapacityStringBuilder()
    {
        int i = 1;
        StringBuilder fraction = new StringBuilder(Limit + 10);
        while (fraction.Length < Limit)
        {
            fraction.Append(i);
            i++;
        }
    }
}

结果:

Concat: 5879ms
StringBuilder as in post: 206ms
StringBuilder calling Append(i): 196ms
StringBuilder with appropriate capacity: 184ms

你的连接比第一个解决方案更快的原因很简单 - 你正在做几个“便宜”的连接(每次复制相对较少的数据)和相对较少的“大”连接(整个字符串至今)。原来,每一步都会复制目前得到的所有数据,显然代价更大。

关于c# - C#中的字符串操作优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/282468/

相关文章:

c 程序无法正确接受输入并产生错误的输出

c - 在 C 中的 while 条件下递减

vba - 如何优化在大量记录上运行的宏?

c - 如何通过 C 中的递归排列来更改叶位置字符串?

string - 解释 MATLAB 中 sprintf 的行为

javascript - 加快数组操作 Google Apps 脚本的执行速度

c# - Regex.Replace 仅替换字符串的开头

c# - 在代码隐藏中设置 Path.Data

c# - 使用绑定(bind)到 List<UserControl> 我该怎么做才能不显示控件

c# - 从无序点绘制连续线