【问题标题】:Speed up string concatenation [duplicate]加快字符串连接[重复]
【发布时间】:2016-12-21 20:46:18
【问题描述】:

我有一个程序可以循环写入一系列文件。文件名是使用来自提供给该方法的对象的参数构造的。

ANTS Performance Profiler 说这很慢,我不知道为什么:

public string CreateFilename(MyObject obj)
{
    return "sometext-" + obj.Name + ".txt";
}

有没有更高效的方法来做到这一点?该方法被点击了数千次,我不知道除了为此目的使用离散方法之外的好方法,因为输入对象超出了我的控制范围并且会定期更改。

【问题讨论】:

  • String.Format() 函数对其进行基准测试,我认为它会稍微快一些。但是tbh,concatenation的代价不是很高,我猜这是不必要的优化?
  • 使用StringBuilder。显然StringBuilder 应该是某种私有字段,只初始化一次。但随心所欲地使用它。
  • @M.kazemAkhgary string.format 在幕后使用了字符串生成器。
  • String.FormatStringBuilder 会明显变慢。不知道为什么有人推荐其中任何一个。
  • @joelc 优化 0.01% 的瓶颈是没有意义的。我不是想在这里搞笑,只是你在浪费时间。瓶颈在别处。

标签: c# string performance


【解决方案1】:

编译器会将您的两个 concat 优化为一次调用:

String.Concat("sometext-", obj.Name, ".txt")

没有更快的方法可以做到这一点。

【讨论】:

【解决方案2】:

如果您改为在类本身中计算文件名,它将运行得更快,以换取在修改对象时降低性能。请注意,如果计算文件名是一个瓶颈,我会非常担心;写入文件比想出它的名字要慢。

请参阅下面的代码示例。当我对它们进行基准测试时(在 LINQPad 5 中),Test2 的运行速度比 Test1 快大约 15 倍。除此之外,Test2 不会不断生成/丢弃微小的字符串对象。

void Main()
{
    Test1();
    Test1();
    Test1();
    Test2();
    Test2();
    Test2();
}

void Test1()
{
    System.Diagnostics.Stopwatch sw = new Stopwatch();
    MyObject1 mo = new MyObject1 { Name = "MyName" };
    sw.Start();
    long x = 0;
    for (int i = 0; i < 10000000; ++i)
    {

        x += CreateFileName(mo).Length;
    }
    Console.WriteLine(x); //Sanity Check, prevent clever compiler optimizations
    sw.ElapsedMilliseconds.Dump("Test1");
}

public string CreateFileName(MyObject1 obj)
{
    return "sometext-" + obj.Name + ".txt";
}

void Test2()
{
    System.Diagnostics.Stopwatch sw = new Stopwatch();
    MyObject2 mo = new MyObject2 { Name = "MyName" };
    sw.Start();
    long x = 0;
    for (int i = 0; i < 10000000; ++i)
    {
        x += mo.FileName.Length;
    }
    Console.WriteLine(x); //Sanity Check, prevent clever compiler optimizations
    sw.ElapsedMilliseconds.Dump("Test2");
}



public class MyObject1
{
    public string Name;
}

public class MyObject2
{
    public string FileName { get; private set;}
    private string _name;
    public string Name
    {
        get 
        {
            return _name; 
        }
        set 
        {
            _name=value;
            FileName = "sometext-" + _name + ".txt";
        }
    }
}

我还测试了将 memoization 添加到 CreateFileName,但与 Test1 相比,它几乎没有提高性能,而且它不可能击败 Test2,因为它执行相同的步骤并增加了哈希查找的开销。

【讨论】:

    猜你喜欢
    • 2014-08-21
    • 2011-09-04
    • 2015-08-23
    • 2020-12-30
    • 2015-07-31
    • 2013-07-21
    • 1970-01-01
    • 2013-09-14
    • 2021-12-10
    相关资源
    最近更新 更多