10

これは単なる好奇心であり、現実世界の助けにはなりません。

式ツリーを使用すると、通常の C# コンパイラと同じように、オンザフライで MSIL を生成できることがわかっています。コンパイラは最適化を決定できるため、.NET で生成された IL の場合はどうなのかと尋ねたくなりますExpression.Compile()。基本的に2つの質問:

  1. コンパイル時に、コンパイラはデバッグ モードとリリース モードで異なる (わずかに異なる) IL を生成する可能性があるため、デバッグ モードとリリース モードでビルドされたときに式をコンパイルすることによって生成される IL に違いはありますか?

  2. また、実行時に IL をネイティブ コードに変換する JIT は、デバッグ モードとリリース モードの両方で大きく異なるはずです。これは、コンパイルされた式にも当てはまりますか? それとも、式ツリーからの IL はまったく jit されていないのでしょうか?

私の理解に欠陥がある可能性があります。念のため訂正してください。

注:デバッガーが切り離されている場合を考慮しています。Visual Studio の「デバッグ」と「リリース」に付随するデフォルトの構成設定についてお尋ねします。

4

3 に答える 3

2

を二乗しintます。

これがよくわかるかどうかはわかりませんが、次の例を思いつきました。

// make delegate and find length of IL:
Func<int, int> f = x => x * x;
Console.WriteLine(f.Method.GetMethodBody().GetILAsByteArray().Length);

// make expression tree
Expression<Func<int, int>> e = x => x * x;

// one approach to finding IL length
var methInf = e.Compile().Method;
var owner = (System.Reflection.Emit.DynamicMethod)methInf.GetType().GetField("m_owner", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(methInf);
Console.WriteLine(owner.GetILGenerator().ILOffset);

// another approach to finding IL length
var an = new System.Reflection.AssemblyName("myTest");
var assem = AppDomain.CurrentDomain.DefineDynamicAssembly(an, System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave);
var module = assem.DefineDynamicModule("myTest");
var type = module.DefineType("myClass");
var methBuilder = type.DefineMethod("myMeth", System.Reflection.MethodAttributes.Static);
e.CompileToMethod(methBuilder);
Console.WriteLine(methBuilder.GetILGenerator().ILOffset);

結果:

デバッグ構成では、コンパイル時のメソッドの長さは 8 ですが、発行されたメソッドの長さは 4 です。

リリース構成では、コンパイル時のメソッドの長さは 4 ですが、発行されたメソッドの長さも 4 です。

デバッグ モードの IL DASM で表示されるコンパイル時の方法:

.method private hidebysig static int32  '<Main>b__0'(int32 x) cil managed
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       8 (0x8)
  .maxstack  2
  .locals init ([0] int32 CS$1$0000)
  IL_0000:  ldarg.0
  IL_0001:  ldarg.0
  IL_0002:  mul
  IL_0003:  stloc.0
  IL_0004:  br.s       IL_0006
  IL_0006:  ldloc.0
  IL_0007:  ret
}

リリース:

.method private hidebysig static int32  '<Main>b__0'(int32 x) cil managed
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       4 (0x4)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldarg.0
  IL_0002:  mul
  IL_0003:  ret
}

免責事項: 何かを結論付けることができるかどうかはわかりませんが (これは長い「コメント」です)、Compile()常に「最適化」が行われるのでしょうか?

于 2013-10-14T10:45:32.227 に答える