NET的抖動已經內置啓發,他LP決定是否To Inline or not to Inline。由於我無法找到阻止內聯的一個很好的理由(見下文),並且在4.5中可以通過AggressiveInlining
來說服它,所以如果願意,抖動可以內聯,可能就是這樣。引述:
如果內聯使代碼更小,則調用它取代了,這是一件好事。請注意,我們正在討論的是NATIVE代碼的大小,而不是IL代碼的大小(這可能會非常不同)。
執行更特定的呼叫現場,更將受益於inlning。因此循環中的代碼應該比不在循環中的代碼更內聯 。
如果內聯暴露出一些重要的優化,那麼內聯是更加希望的。具體來說,值類型參數 的方法會因爲這樣的優化而受益比正常情況更多,因此 有內聯這些方法的偏好是很好的。
因此,X86 JIT編譯器使用啓發式是,給定的一個內聯 候選。
如果方法未內聯,估計呼叫站點的大小。
估計呼叫站點的大小(如果它是內聯的)(這是基於IL的估計,我們使用一個簡單的狀態機(Markov 模型),使用大量實際數據創建該估計器邏輯)
計算乘數。默認情況下,它是1
增加乘數如果代碼是在一個循環(當前啓發式它對顛簸到5環)
增加倍數,如果它看起來像結構優化將一命嗚呼。
If InlineSize < = NonInlineSize * Multiplier做內聯。
下面是我嘗試去的這條底線的描述,它可以幫助其他人在類似的情況。
我可以在.Net 4.5(x68和x64)上重現它,但是我不知道爲什麼它沒有被內聯,因爲它沒有像inlining show stoppers那樣的虛擬方法或者消耗多於32個字節。這是30個字節的短:
.method public hidebysig static bool IsControl(char c) cil managed
{
// code size 30 (0x1e)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: blt.s IL_0009
IL_0004: ldarg.0
IL_0005: ldc.i4.s 31
IL_0007: ble.s IL_001c
IL_0009: ldarg.0
IL_000a: ldc.i4.s 127
IL_000c: blt.s IL_001a
IL_000e: ldarg.0
IL_000f: ldc.i4 0x9f
IL_0014: cgt
IL_0016: ldc.i4.0
IL_0017: ceq
IL_0019: ret
IL_001a: ldc.i4.0
IL_001b: ret
IL_001c: ldc.i4.1
IL_001d: ret
} // end of method Program::IsControl
當啓用AggressiveInlining
(你說你不能,因爲你是對的.Net 3.5),則不僅調用get內聯,但聯的代碼被徹底忽略, - 因爲它不應該使用返回值:
--- Program.cs --------------------------------------------
IsControl('\0');
00000000 ret
NB我不知道,如果你知道,除了使用發佈版本模式,你have to
- 選擇工具=>選項=>調試=>常規,並確保盒標有「禁止JIT優化模塊加載「未選中。
- 確保未選中標記爲「啓用我的代碼」的框。
爲了看到JIT優化的代碼。如果不這樣做,你會得到以下代替上述單ret
聲明:
--- Program.cs --------------------------------------------
IsControl('\0');
00000000 push rbp
00000001 sub rsp,30h
00000005 lea rbp,[rsp+30h]
0000000a mov qword ptr [rbp+10h],rcx
0000000e mov rax,7FF7F43335E0h
00000018 cmp dword ptr [rax],0
0000001b je 0000000000000022
0000001d call 000000005FAB06C4
00000022 xor ecx,ecx
00000024 call FFFFFFFFFFFFD3D0
00000029 and eax,0FFh
0000002e mov dword ptr [rbp-4],eax
00000031 nop
}
00000032 nop
00000033 lea rsp,[rbp]
00000037 pop rbp
00000038 ret
下,短(而不是等同)方法BTW將獲得內聯即使沒有AggressiveInlining
:
public static bool IsControl(char c)
{
return c <= 31 || c >= 127;
}
你跟一個發佈版本檢查嗎?因爲在Debug中,編譯器將保留所有的功能,以便調試應用程序。 – MicroVirus
@Micro是的,我做 –
只是清除明顯的:)當IsControl是私人的時候會發生同樣的事情嗎? – MicroVirus