c# - MethodImpl(AggressiveInlining) - 它有多激进?

标签 c# .net

所以我看了一下 MethodImplAttribute我遇到了MethodImplOptions.AggressiveInlining这被描述为:

The method should be inlined if possible.

哦哦,我心想,这听起来很有趣——我可以假装自己比编译器更聪明,并使用我邪恶意志的力量和几个方括号强制代码内联,哈,哈,哈。 ..

因此我启动了 Visual Studio 2013,创建了一个控制台应用程序,将 .NET 版本设置为 4.5.1 并编写了程序以结束所有程序(当然是在 Release 模式下编译) :

using System;
using System.Runtime.CompilerServices;

namespace ConsoleApplication1
{   
    public static class SoHelpful
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int GetSomeValueProbablyTwelve()
        {
            return 12;
        }
        [MethodImpl(MethodImplOptions.NoInlining)]
        public static int GetSomeValueLikelyThirteen()
        {
            return 13;
        }
        public static int GetSomeValueMaybeItIsTwentyEight()
        {
            return 29;
        }
    }

    class Program
    {       
        static void Main()
        {
            int twelve = SoHelpful.GetSomeValueProbablyTwelve();
            int thirteen = SoHelpful.GetSomeValueLikelyThirteen();
            int twentyNine = SoHelpful.GetSomeValueMaybeItIsTwentyEight();
            Console.WriteLine((twelve + thirteen + twentyNine));
        }
    }
}

现在,如果我快速执行 ildasm,我会看到:

.class public abstract auto ansi sealed beforefieldinit ConsoleApplication1.SoHelpful
       extends [mscorlib]System.Object
{
  .method public hidebysig static int32  GetSomeValueProbablyTwelve() cil managed
  {
    // Code size       3 (0x3)
    .maxstack  8
    IL_0000:  ldc.i4.s   12
    IL_0002:  ret
  } // end of method SoHelpful::GetSomeValueProbablyTwelve

  .method public hidebysig static int32  GetSomeValueLikelyThirteen() cil managed noinlining
  {
    // Code size       3 (0x3)
    .maxstack  8
    IL_0000:  ldc.i4.s   13
    IL_0002:  ret
  } // end of method SoHelpful::GetSomeValueLikelyThirteen

  .method public hidebysig static int32  GetSomeValueMaybeItIsTwentyEight() cil managed
  {
    // Code size       3 (0x3)
    .maxstack  8
    IL_0000:  ldc.i4.s   29
    IL_0002:  ret
  } // end of method SoHelpful::GetSomeValueMaybeItIsTwentyEight

} // end of class ConsoleApplication1.SoHelpful

.class private auto ansi beforefieldinit ConsoleApplication1.Program
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main() cil managed
  {
    .entrypoint
    // Code size       29 (0x1d)
    .maxstack  2
    .locals init ([0] int32 twelve,
             [1] int32 thirteen,
             [2] int32 twentyNine)
    IL_0000:  call       int32 ConsoleApplication1.SoHelpful::GetSomeValueProbablyTwelve()
    IL_0005:  stloc.0
    IL_0006:  call       int32 ConsoleApplication1.SoHelpful::GetSomeValueLikelyThirteen()
    IL_000b:  stloc.1
    IL_000c:  call       int32 ConsoleApplication1.SoHelpful::GetSomeValueMaybeItIsTwentyEight()
    IL_0011:  stloc.2
    IL_0012:  ldloc.0
    IL_0013:  ldloc.1
    IL_0014:  add
    IL_0015:  ldloc.2
    IL_0016:  add
    IL_0017:  call       void [mscorlib]System.Console::WriteLine(int32)
    IL_001c:  ret
  } // end of method Program::Main

  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Program::.ctor

} // end of class ConsoleApplication1.Program

有意思,所以定义了三个方法:

.method public hidebysig static int32  GetSomeValueLikelyThirteen() cil managed noinlining
.method public hidebysig static int32  GetSomeValueProbablyTwelve() cil managed
.method public hidebysig static int32  GetSomeValueMaybeItIsTwentyEight() cil managed

因此,看起来我的主动内联属性丢失了。

我可以在 GetSomeValueLikelyThirteen 上看到 noinlining,但 GetSomeValueProbablyTwelveGetSomeValueMaybeItIsTwentyEight 是相同的。

所以发生了什么?我想有几种可能性:

  1. C# 编译器已经意识到 GetSomeValueProbablyTwelve 不能被内联,所以不会用我愚蠢的属性白痴来麻烦 JIT。
  2. C# 编译器已经意识到 GetSomeValueMaybeItIsTwentyEight 可以被内联,这就是为什么它在 IL 中与 GetSomeValueProbablyTwelve 相同(所以我的归因在很大程度上是毫无意义和愚蠢的这种情况也是如此)。
  3. 有一些编译设置或我必须调整的东西才能识别属性。
  4. 它根本没有在 C# 中实现。
  5. 我发现了一个错误
  6. 其他

那么,有人知道它是什么吗?

最佳答案

MethodImplAttributes.AggressiveInlining 编译为 MethodDef 元数据表(ECMA-335 Partition II §22.26)的 ImplFlags 列中的标志。此属性的值在 Partition II §23.1.11 中列出,但 AggressiveInlining 未记录(表中不存在 0x0100 的值)。

在编译过程中,编译器会从元数据中删除属性本身。如果方法的 ImplFlags 中设置了 0x0100 位,则反汇编器必须实现特殊逻辑来添加属性。

关于c# - MethodImpl(AggressiveInlining) - 它有多激进?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20517103/

相关文章:

c# - 将 Excel 模板保存为资源的一部分 C# Visual Studio

.net 卡在 Application.DoEvents

.net - 发送自动短信

c# - 如何测量函数运行了多长时间?

c# - 计时器委托(delegate)周围的内存泄漏

c# - 从 C# 调用接受调用者分配的结构数组的 C 函数

c# - 空旗是坏习惯吗?

c# - 获取特定文化的 DateTime.DayOfWeek

javascript - Jint 和 JavaScript 之间的通信

c# - 如何使用 C#-WPF-Entity-Framework Code First 应用程序创建数据库备份?