从逻辑上讲,我总是认为非常简短的方法会被C#编译器内联,因此与简单地在代码中输入代码相比,不会显示任何开销手工方法...甚至没有简单的方法来内联(?)
直到今天 - 当我试图基准各种方法和手动内联代码。结果是(对我来说)即使是最简单的代码也会显示一个方法调用开销,而不是手动内联对手。
其实,我找不到任何线索任何方法被内联 - 所以我跑了一个简单的测试。使用
系统:
- 英特尔C2D E7200(双核)2.53GHz的
- 4GB DDR2
- 64位Windows 7
- .NET 4.0
- 的Visual Studio 2010旗舰版
所有的测试都进行了而没有得到g和使用版本配置(优化代码)。
下面是我用于基准的代码:
static void Main()
{
const int iterations = 250000000; // 250 million iterations
Thread.Sleep(1000); // sleep for one second
var sw = new Stopwatch();
int s = 0;
sw.Start();
for (int i = 0; i < iterations; i++)
{
// incrementing s by 1 in various ways
}
sw.Stop();
Console.WriteLine("Time: {0}ms", sw.ElapsedMilliseconds);
}
[1]首先,我已经简单地基准一个简单的增量命令:从5次
// in Main
for (int i = 0; i < iterations; i++)
{
s = s + 1;
}
结果:
- 867ms
- 877ms
- 868ms
- 865ms
- 870ms
[2]切换到一个方法调用:
static int Increment(int a)
{
return a + 1;
}
...
// in Main
for (int i = 0; i < iterations; i++)
{
s = Increment(s);
}
从5个运行个
结果:
- 2161ms
- 2159ms
- 2194ms
- 2177ms
- 2163ms
哎哟!显然这个方法有一个开销。
我试过使用反射,并从Increment
方法中打印MethodBase.GetCurrentMethod().Name
;它确实在打印Increment
- 意味着该方法不是内联的。
接下来我试图将[MethodImpl(MethodImplOptions.NoInlining)]
属性添加到方法 - ,但基准时间保持完全相同。
在调试模式下,如果将优化代码设置为false,则第一个测试稍慢,而第二个测试慢两倍;并且否内联属性不会影响性能。
上午我在这里做得不对,我无法让即使是这样一个简单的方法,没有工作的开销?这是为什么发生?
当然,这不能被期望的行为 - 或者它?
注意:Java中的类似测试显示此类方法调用没有开销。 (使用Eclipse + JDK 1.7,Java也似乎很多在这个快。)
注意,在.NET 4.5中,你可以强制编译器尝试并内联你的方法:http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions%28v=VS.110%29.aspx – Polity