【发布时间】:2014-04-10 09:20:14
【问题描述】:
我正在优化我的代码,我注意到使用属性(甚至是自动属性)对执行时间有深远的影响。请看下面的例子:
[Test]
public void GetterVsField()
{
PropertyTest propertyTest = new PropertyTest();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
propertyTest.LoopUsingCopy();
Console.WriteLine("Using copy: " + stopwatch.ElapsedMilliseconds / 1000.0);
stopwatch.Restart();
propertyTest.LoopUsingGetter();
Console.WriteLine("Using getter: " + stopwatch.ElapsedMilliseconds / 1000.0);
stopwatch.Restart();
propertyTest.LoopUsingField();
Console.WriteLine("Using field: " + stopwatch.ElapsedMilliseconds / 1000.0);
}
public class PropertyTest
{
public PropertyTest()
{
NumRepet = 100000000;
_numRepet = NumRepet;
}
int NumRepet { get; set; }
private int _numRepet;
public int LoopUsingGetter()
{
int dummy = 314;
for (int i = 0; i < NumRepet; i++)
{
dummy++;
}
return dummy;
}
public int LoopUsingCopy()
{
int numRepetCopy = NumRepet;
int dummy = 314;
for (int i = 0; i < numRepetCopy; i++)
{
dummy++;
}
return dummy;
}
public int LoopUsingField()
{
int dummy = 314;
for (int i = 0; i < _numRepet; i++)
{
dummy++;
}
return dummy;
}
}
在我的机器上的Release 模式下,我得到:
Using copy: 0.029
Using getter: 0.054
Using field: 0.026
在我的情况下这是一场灾难——如果我想获得最佳性能,最关键的循环就不能使用任何属性。
我在这里做错了什么?我在想这些应该是JIT optimizer 旁边的inlined。
【问题讨论】:
-
当您说“处于发布模式”时,您是指发布 build 配置,还是在没有调试器的情况下运行?如果您在调试器中运行,我完全希望看到显着的影响。另请注意,循环如此紧凑是非常不寻常的......并且对微优化只是证明是瓶颈的应用程序的那些部分是合理的。跨度>
-
我刚刚自己测试了代码,x86 JIT使得属性访问和字段访问基本一样。 x64 JIT 显示了您在问题中提出的行为。您可能想尝试使用即将推出的新 x64 JIT:blogs.msdn.com/b/dotnet/archive/2014/02/27/…
-
对 - 我会尝试在独立环境中进行性能测试,尽可能少地干扰结果,就个人而言。 (我喜欢使用简单的控制台应用程序来执行此操作。)但是,正如我所说,看起来 x64 JIT 在内联方面不如 x86 JIT 聪明。
-
虽然它没有解释差异:我看不出这会产生“深远的影响”还是“灾难”。您正在执行一段代码十亿次,但仍然在最坏的情况下只需要 54 毫秒。如果您想要更多性能,请使用 C 或 ASM 而不是 .Net。
-
@AndreasMüller 不,这不是一场灾难完全 IMO。如果这个小的性能问题是一个真正的问题,那么我很抱歉,但是会有 吨 其他类似的性能问题或 更糟 因为 .Net。第一个明显的例子是 垃圾收集器执行,这将是一场真正的灾难,而不仅仅是每次执行几纳秒的损失。
标签: c# .net performance optimization