質問

アプリケーションでは、多くの「スタックイントロスペクティブ」コードを観察しました。 いいえ 彼らの正しさのためにインラードされています。そのような方法は、一般的に次の呼び出しを伴います。

  • MethodBase.GetCurrentMethod
  • Assembly.GetCallingAssembly
  • Assembly.GetExecutingAssembly

今、私はこれらの方法を取り巻く情報が非常に混乱していることがわかります。実行時間はGetCurrentMethodを呼び出すメソッドをインラインにしないと聞いたことがありますが、その効果に関するドキュメントは見つかりません。 StackoverFlowの投稿を何度か見てきました。 これです, 、CLRがインラインのクロスアセンブリ呼び出しではないことを示しますが、 GetCallingAssembly ドキュメンテーション それ以外の場合は強く示します。

また、大いに悪用されています [MethodImpl(MethodImplOptions.NoInlining)], 、しかし、CLRがこれを「リクエスト」または「コマンド」と見なしているかどうかはわかりません。

インランスについて尋ねていることに注意してください 資格 契約の観点から、 いいえ ジッターの現在の実装が、実装の問題のために方法を検討することを拒否したとき、またはジッターが最終的に最終的に終わるときについて 選択 トレードオフを評価した後、適格な方法をインラインにする。読みました これこれ, 、しかし、彼らは最後の2つのポイントにもっと焦点を合わせているようです(methodimpoptions.noinliningと "exotic il命令]の言及がありますが、これらはとしてではなく、ヒューリスティックとして提示されているようです 義務).

CLRはいつですか 許可された インラインに?

役に立ちましたか?

解決

これはジッターの実装の詳細であり、X86およびX64ジッターには微妙に異なるルールがあります。これは、ジッターに取り組んだチームメンバーのブログ投稿にさりげなく文書化されていますが、チームは確かにルールを変更する権利を留保します。あなたはすでにそれらを見つけたようです。

他のアセンブリからのインラインメソッドは確かにサポートされています。そうでなければ、多くの.NETクラスは非常に惨めに機能します。 console.writeLine()用に生成されたマシンコードを見ると、作業中に見ることができます。単純な文字列を渡すと、しばしばインラインになります。これを自分で確認するには、リリースビルドに切り替えてデバッガーオプションを変更する必要があります。ツール +オプション、デバッグ、一般、Untick「モジュール負荷のJIT最適化を抑制」。

それ以外の場合は、MethodImpoptionsを検討する正当な理由はありません。悪意のあるものは、そもそもそれが存在する理由です。実際、内部ヘルパーメソッドを呼び出す多くの小さなパブリックメソッドに関する.NETフレームワークで意図的に使用されています。例外スタックトレースを診断しやすくします。

他のヒント

ハンス・パサントの答えにもかかわらず、 ここ 最初に2004年の時点でいくつかのヒントがあり、さらに最新情報をさらに下げます。それらは変更される可能性がありますが、インライン化の対象となる方法を作成する場合、何を探すべきかについてのアイデアを提供します。

JITはインラインではありません。

  • methodimploptions.noinliningでマークされた方法
  • ILの32バイトを超える方法
  • 仮想メソッド
  • パラメーターとして大きな値タイプをとる方法
  • Marshalbyrefクラスの方法
  • 複雑なフローグラフを含む方法
  • その他のよりエキゾチックな基準を満たす方法

特に、あります methodimploptions.aggressioninlining, 、32バイトの制限(または最近とあなたのプラットフォームのためにそれが何であれ)を持ち上げることになっています。

.NET 3.5は、それが決定するのに役立つヒューリスティックを追加しました インラインまたはインラインではないか, 、これはおそらく良いことですが、開発者がジッターの決定を予測することは難しくなります。

記事からの引用:

  1. インラインがコードを小さくする場合、それを通話する場合、それは常に良いです。 ILコードサイズではなく、ネイティブコードサイズについて話していることに注意してください(これはまったく異なる場合があります)。

  2. 特定のコールサイトが実行されるほど、Inlningの恩恵を受けることができます。したがって、ループのコードは、ループにないコードよりも多くインラインドするに値します。

  3. インラインが重要な最適化を公開する場合、インラインはより望ましいものです。特定の方法では、このような最適化のために、値タイプの引数を持つ方法は通常よりも利益を得ているため、これらの方法をインラインにするバイアスを持つことは良いことです。

したがって、X86 JITコンパイラが使用するヒューリスティックは、インライン候補を与えられます。

  1. メソッドがインラインされていない場合は、コールサイトのサイズを推定します。

  2. インライン化された場合、コールサイトのサイズを推定します(これはILに基づく推定であり、この推定器ロジックを形成するために多くの実際のデータを使用して作成された単純な状態マシン(Markovモデル)を使用します)

  3. 乗数を計算します。デフォルトでは1です

  4. コードがループにある場合、乗数を増やします(現在のヒューリスティックがループで5にぶつかります)

  5. 構造体の最適化が始まるように見える場合は、乗数を増やします。

  6. inlinesize <= nonlinesize *乗数はインラインを行います。

その間 ハンスの答え 正しいです、1つの省略があります。必ずしもメソッドがインランスの対象となる場合ではなく、メソッドがいつであるかについてです いいえ.

抽象的および仮想的な方法は、CLRにインランスする資格がありません.

メソッドがある条件を削るので、注意することが重要です 五月 インラインドしてください。

このスレッドにmethodbase.getCurrentMethodのインラインに関する詳細があります http://prdlxvm0001.codify.net/pipermail/ozdotnet/2011-march/009085.html

ひどく言い換えると、refcrawlmarkがインライン化されている呼び出し方法を止めないと述べています。ただし、requiresecobjectは、発信者がインラインされているのを止めるという副作用を持っています。

さらに、Assembly.GetCallingAssemblyとAssembly.GetExexCuteSemblyメソッドには、この属性がありません。

2003年にMSDNに投稿された記事がありました 高性能管理アプリを作成します これは、いくつかの基準の概要を非常に明確にカバーしています。

  • ILの32バイトを超える方法は、インラインではありません。
  • 仮想関数はインラインではありません。
  • 複雑なフロー制御を備えた方法は、並んでいません。複雑なフロー制御は、/then/else以外のフロー制御です。この場合、スイッチまたはwhile。
  • 例外をスローするメソッドは、まだインランスの候補ですが、例外ブロックを含む方法はインラインではありません。
  • 方法の正式な引数のいずれかが構造体である場合、メソッドはインライン化されません。

2012年のSacha Goldshteinのブログ記事 CLRの積極的なインライン 同じアドバイスがたくさんあります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top