MethodImpl(AggressiveInlining) - どれくらい積極的か? 質問する

MethodImpl(AggressiveInlining) - どれくらい積極的か? 質問する

そこで私はちょっとメソッド実装属性そして私は出会ったメソッド実装オプション.AggressiveInlining次のように説明されます:

可能であれば、メソッドをインライン化する必要があります。

ああ、面白そうだな、と私は思いました。コンパイラよりも賢いふりをして、邪悪な意志の力といくつかの角括弧だけを使って、コードを強制的にインライン化できるのです、ハハハ...

そこで、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));
        }
    }
}

さて、Swift 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

興味深いことに、次の 3 つのメソッドが定義されています。

.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

したがって、積極的なインライン化属性が失われているように見えます。

わかりますnoinliningGetSomeValueLikelyThirteenGetSomeValueProbablyTwelveと はGetSomeValueMaybeItIsTwentyEight同じです。

それで何が起こったのでしょうか? いくつかの可能性があると思います:

  1. C# コンパイラは、GetSomeValueProbablyTwelveインライン化できないことを認識しているので、私の愚かな属性の愚かさで JIT に問題を引き起こすことはありません。
  2. C# コンパイラは、GetSomeValueMaybeItIsTwentyEightインライン化できることを認識しており、これが IL 内で同じである理由ですGetSomeValueProbablyTwelve(したがって、この場合も、私の属性付けはほとんど無意味かつ愚かなものでした)。
  3. 属性が認識されるようにするには、コンパイル設定などを微調整する必要があります。
  4. 全く実装されていませんC#
  5. バグを発見しました
  6. その他

それで、それがどれか誰か知っていますか?

ベストアンサー1

MethodImplAttributes.AggressiveInliningフラグにコンパイルされます実装フラグの列メソッド定義メタデータ テーブル (ECMA-335 パーティション II §22.26)。この属性の値は、パーティション II §23.1.11 に記載されていますが、AggressiveInlining文書化されていません (0x0100 のテーブルに値が存在しません)。

コンパイルプロセス中に、コンパイラはメタデータから属性自体を削除します。逆アセンブラは、0x0100ビットが設定されている場合、属性を再度追加するための特別なロジックを実装する必要があります。実装フラグ方法については。

おすすめ記事