我有一个程序会在循环中编写一系列文件。使用提供给方法的对象中的参数构造文件名。
ANTS Performance Profiler说这是狗慢,我不确定原因:
public string CreateFilename(MyObject obj)
{
return "sometext-" + obj.Name + ".txt";
}
有更高效的方法吗?该方法被击中了数千次,并且我不知道除了用于此目的的离散方法之外的好方法,因为输入对象不受我的控制并且经常改变。
答案 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,因为它执行等效的步骤以及散列查找的额外开销。