是静态方法热切编译(JIT'ed)?(Are static methods eagerly

2019-08-01 02:59发布

按我的理解,每当该方法被称为第一次两个实例方法和静态方法来处理由CLR编译器和IL代码同样是即时编译。 今天,我和我的同事讨论,他告诉我,静态方法不处理方式与实例方法相同。 即静态方法只要组件被加载到应用程序域而实例方法是即时编译因为他们是所谓的第一次即时编译。

其实我一头雾水,不明白了一个道理,为什么静态方法应该由CLR急切地编译? 我明白关于对象或当使用约束的执行区域静态构造或临界终结的释放方法。 但是,如果一些类有静态和实例相结合的方法,我真的不知道为什么所有的静态方法将尽快包含类的组件将被加载到内存中实时编译的?

请帮我理解这种行为。

Answer 1:

纵观当方法得到JIT使用的WinDbg / SOS编译显示静态方法之前,不会调用它们编译。

考虑下面的类:

class SomeType
{
    [MethodImpl(MethodImplOptions.NoInlining)]
    public void InstanceMethod()
    {
        Console.WriteLine("instance");
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static void TypeMethod()
    {
        Console.WriteLine("type");
    }
}

我用的是NoInlining选项来阻止编译器内联在发布版本这些方法。

如果我运行一个小的应用程序像下面并附着在WinDbg当方法得到JIT编译的,我可以观察到。

var st = new SomeType();

Console.WriteLine("attach");
Console.ReadLine();

Console.WriteLine("calling methods");
st.InstanceMethod();
SomeType.TypeMethod();

Console.ReadLine();

在连接方法表的点SomeType看起来是这样的:

0:004> !dumpmt -md 0041387c
EEClass:         004114d4
Module:          00412e94
Name:            ConsoleApplication2.SomeType
mdToken:         02000007
File:                c:\temp\ConsoleApplication1\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6d374960 6d076728 PreJIT System.Object.ToString()
6d368790 6d076730 PreJIT System.Object.Equals(System.Object)
6d368360 6d076750 PreJIT System.Object.GetHashCode()
6d3616f0 6d076764 PreJIT System.Object.Finalize()
0041c035 00413874   NONE ConsoleApplication2.SomeType..ctor()
0041c02d 0041385c   NONE ConsoleApplication2.SomeType.InstanceMethod()
0041c031 00413868   NONE ConsoleApplication2.SomeType.TypeMethod()

该方法已被显式调用后,它看起来是这样的:

0:007> !dumpmt -md 0041387c
EEClass:         004114d4
Module:          00412e94
Name:            ConsoleApplication2.SomeType
mdToken:         02000007
File:            c:\temp\ConsoleApplication1\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6d374960 6d076728 PreJIT System.Object.ToString()
6d368790 6d076730 PreJIT System.Object.Equals(System.Object)
6d368360 6d076750 PreJIT System.Object.GetHashCode()
6d3616f0 6d076764 PreJIT System.Object.Finalize()
0041c035 00413874   NONE ConsoleApplication2.SomeType..ctor()
004700e0 0041385c    JIT ConsoleApplication2.SomeType.InstanceMethod()
00470110 00413868    JIT ConsoleApplication2.SomeType.TypeMethod()

即方法不JIT编译直到他们实际上是调用。

(根据记录这是在.NET 4.5完成)



Answer 2:

据我所知静态方法不是从实例方法不同threated,也许你的同事都在谈论,实际上被调用,一旦该类型是在调用程序集称为静态构造函数 。 从而实时编译。

更新4.0(感谢@JulienLebosquain指点)

.NET 4.0采用的是所谓的懒惰类型的初始化,基本上改变行为和静态构造函数调用只是当尽快静态字段加入的第一次。



文章来源: Are static methods eagerly compiled (JIT'ed)?