從邏輯上講,我總是認爲非常簡短的方法會被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