加速字符串连接

时间:2016-12-21 20:46:19

标签: c# string performance

我有一个程序会在循环中编写一系列文件。使用提供给方法的对象中的参数构造文件名。

ANTS Performance Profiler说这是狗慢,我不确定原因:

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

有更高效的方法吗?该方法被击中了数千次,并且我不知道除了用于此目的的离散方法之外的好方法,因为输入对象不受我的控制并且经常改变。

2 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分: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";
        }
    }
}

我还测试了向CreateFileName添加memoization,但它几乎没有提高Test1的性能,并且它不可能击败Test2,因为它执行等效的步骤以及散列查找的额外开销。