.NET(C#):MethodImplOptions.NoInlining来阻止JIT内联方法(转载)

 

众所周知,引用程序集的加载并不是在程序开始运行时就全部加载的,CLR会加载相应的程序集当该程序集的类型被第一次使用。更具体的说,当一个方法被JIT时,CLR会确保该方法中的类型所在的程序集被加载。

 

比如我们的主程序Mgen.exe引用一个类库ClassLibrary1,后者有一个类型Class1:

 

这段代码,分别在使用ClassLibrary1的一个类型之前对当前应用程序域加载的程序集进行枚举:

        static void Main()

        {

            foreach (var ass in AppDomain.CurrentDomain.GetAssemblies())

                Console.WriteLine(ass.GetName().Name);

 

            Console.WriteLine("=== 分割线 ===");

 

            //使用ClassLibrary1的类型

            doo();

 

            foreach (var ass in AppDomain.CurrentDomain.GetAssemblies())

                Console.WriteLine(ass.GetName().Name);

 

        }

 

        static void doo()

        {

            var obj = new ClassLibrary1.Class1();

        }

 

运行代码(注意要在Release发布模式),程序会输出:

mscorlib

Mgen

ClassLibrary1

=== 分割线 ===

mscorlib

Mgen

ClassLibrary1

 

为何ClassLibrary1出现在第一个列表中?事实上如果JIT不对doo进行内联处理的话,当Main方法被JIT后,CLR是不会觉察到Main方法会使用ClassLibrary1的,因此ClassLibrary1是不会出现在列表中的,但运行时刻JIT的优化使得doo被内联在Main方法中,这样整个代码相当于:

        static void Main()

        {

            //省略

 

            //内联的doo

            var obj = new ClassLibrary1.Class1();

 

            //省略

        }

 

使用MethodImplOptions.NoInlining可以阻止JIT在编译时把某些方法进行内联处理。注意MethodImpleOptions枚举要用在MethodImpl特性上。(另外MethodImpleOptions枚举还有其他功能,比如常见的MethodImpleOptions.Synchronized用来进行线程同步。可以参考MSDN:http://msdn.microsoft.com/zh-cn/library/system.runtime.compilerservices.methodimploptions.aspx

最后注意上述类都在System.Runtime.CompilerServices命名空间内。

 

这样的话在doo方法上加入MethodImpl特性:

        //+ System.Runtime.CompilerServices;

        [MethodImpl(MethodImplOptions.NoInlining)]

        static void doo()

        {

            var obj = new ClassLibrary1.Class1();

        }

 

再次编译整个程序,输出:

mscorlib

Mgen

=== 分割线 ===

mscorlib

Mgen

ClassLibrary1

 

可以看到,此时由于doo没有被内联,JIT编译Main方法后没有发现使用其他程序集,所以第一次枚举程序集没有ClassLibrary1,而当doo方法真正执行后,更确切的说是在doo方法被JIT后,但在执行前,CLR会加载ClassLibrary1。所以第二次枚举应用程序域中的程序集时,ClassLibrary1在列表中。

 

如果在Debug调试模式下运行程序,结果也是上面的输出(ClassLibrary1不在列表1),因为调试模式下,JIT方法内联优化是被禁止的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值