2013-12-22 27 views
2

我正在測試Interlocked.Incrementlock如何在我的計算機架構上運行,因爲我在this article中讀取了以下行。Interlocked.Increment與鎖定在調試與發佈模式

正如使用Interlocked.Increment重寫的,該方法應該執行得更快,至少在某些體系結構上。

使用下面的代碼我確信值得查看我的項目中的鎖。

var watch = new Stopwatch(); 
var locker = new object(); 
int counter = 0; 

watch.Start(); 
for (int i = 0; i < 100000000; i++) 
{ 
    lock (locker) 
    { 
     counter++; 
    } 
} 
watch.Stop(); 
Console.WriteLine(watch.Elapsed.TotalSeconds); 

watch.Reset(); 
counter = 0; 

watch.Start(); 
for (int i = 0; i < 100000000; i++) 
{ 
    Interlocked.Increment(ref counter); 
} 
watch.Stop(); 
Console.WriteLine(watch.Elapsed.TotalSeconds); 

我得到穩定的結果與近似值2.4S用於鎖定和1.2S的互鎖。然而,我驚訝地發現,在釋放模式下運行此代碼僅提高了聯鎖的值,大約爲0.7s並且鎖定時間保持不變。這是爲什麼?在鎖定不是鎖定的釋放模式下,互鎖是如何優化的?

+1

通常,所有性能測量都應該只在發佈模式下完成。調試模式性能測量不相關。讀取由C#編譯器提供的MSIL,可能代碼太優化了(例如,Interlocked被++替換)。 –

+1

無鎖區域需要兩條互鎖指令。您測量的數字完美地顯示了這一點,至少在調試模式下。順便說一句,你的基準測試意味着很少,因爲同步成本取決於鎖定和緩存行爭用。你的基準假設沒有。 – usr

+0

@usr如果你能寫更多關於它並將其作爲答案發布,那將是非常好的。我不明白MSIL,因爲我建議閱讀整篇文章,但我仍然不完全理解,因此有關該主題的更多信息將受到歡迎。 –

回答

3

您必須查看生成的機器代碼才能看到差異,Debug + Windows + Disassembly。在Interlocked.Increment()調用的調試內部版本:

00FC27AD call  7327A810 

發佈版本版本:

025F279D lock inc dword ptr [ebp-24h] 

或者換句話說,抖動優化得到了在發佈版本很聰明,更換調用輔助函數到單機機器指令。

優化只是沒有比這更好。同樣的優化不能應用於在聲明下的Monitor.Enter()方法調用,它是一個在CLR中實現並且不能內聯的相當實際的函數。它除了Interlocked.Increment()之外還有很多其他功能,它允許操作系統在線程阻塞嘗試獲取監視器並維護一個等待線程隊列時重新安排時間。這對確保良好的併發性非常重要,而不是在測試代碼中,因爲鎖完全沒有爭議。謹防不符合實際使用情況的綜合基準。