Are static methods eagerly compiled (JIT'ed)?

前端 未结 2 2036
猫巷女王i
猫巷女王i 2021-02-08 08:43

Per my understanding, both instance methods and static methods are treated same by CLR compiler and the IL code is JITted whenever the method is called first time. Today I had a

2条回答
  •  南笙
    南笙 (楼主)
    2021-02-08 09:34

    Looking at when the methods get JIT compiled using WinDbg/SOS shows that static methods are not compiled prior to calling them.

    Consider the following class:

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

    I use the NoInlining option to prevent the compiler from inlining these methods in a release build.

    If I run a small app like below and attach the WinDbg I can observe when the methods get JIT compiled.

    var st = new SomeType();
    
    Console.WriteLine("attach");
    Console.ReadLine();
    
    Console.WriteLine("calling methods");
    st.InstanceMethod();
    SomeType.TypeMethod();
    
    Console.ReadLine();
    

    At the point of attach the method table for SomeType looks like this:

    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()
    

    After the methods have been explicitly invoked it looks like this:

    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()
    

    I.e. the methods are not JIT compiled until they are actually invoked.

    (For the record this was done on .NET 4.5)

提交回复
热议问题