JIT 在 .NET 中的工作方式是,在方法被抖动之前,方法表条目指向一个小存根,该存根将在调用时对该方法进行 JIT。之后,方法表会更新以引用 JIT 编译代码的位置。
鉴于只有调用的方法才会进行 JIT 编译,因此未调用的方法不会产生 JIT 开销。
JIT 编译器将在需要时编译整个方法。如果是发布版本,则可以优化构建代码,但否则该方法将被完整编译。
您可以使用 WinDbg/SOS 检查方法表。考虑以下:
class SomeType
{
public void Called()
{
Console.WriteLine("called");
}
public void NotCalled()
{
Console.WriteLine("not called");
}
}
假设我们创建一个实例SomeType
, call Called
然后检查方法表SomeType
。在 x86 上你会看到类似这样的内容:
0:000> !dumpmt -md 00a7381c
EEClass: 00a712d0
Module: 00a72e94
Name: ConsoleApplication1.SomeType
mdToken: 02000002
File: c:\temp\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe
BaseSize: 0xc
ComponentSize: 0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
Entry MethodDe JIT Name
72ca4960 729a6728 PreJIT System.Object.ToString()
72c98790 729a6730 PreJIT System.Object.Equals(System.Object)
72c98360 729a6750 PreJIT System.Object.GetHashCode()
72c916f0 729a6764 PreJIT System.Object.Finalize()
00df00d8 00a73814 JIT ConsoleApplication1.SomeType..ctor()
00df0110 00a737fc JIT ConsoleApplication1.SomeType.Called()
00a7c031 00a73808 NONE ConsoleApplication1.SomeType.NotCalled()
请注意Called
是 JIT 编译的,但是因为我们还没有调用NotCalled
然而,它还没有被 JIT 编译。
另外,请注意来自的方法object
全部都经过 PreJIT 编译。
请记住,在发布版本中,可能会内联短方法,在这种情况下,它们不会作为方法调用,而只是作为调用站点生成的代码的一部分包含在内。