2012-01-17 6 views
2

メソッドがインライン化する可能性があります。それを防ぐ属性があります(「それにはattがあります」)。しかし、明らかに、メソッドは、JITter(http://www.hanselman.com/blog/ReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspx)によるテールコール最適化のために、x64上に独自のスタックフレームを取得しない可能性があります。これはMethodBase.GetCurrentMethodの動作に影響しますか?MethodBase.GetCurrentMethodはいつ信頼性が高い/予測可能ですか?

私が見つけることができる議論は主にインライン化(​​When is a method eligible to be inlined by the CLR?)です。これらの議論はそれ自体が興味深いものですが、私の問題は実際には、MethodBase.GetCurrentMethodが、プログラマーがコールをしたのと同じ方法を特定するために頼ることができる状況があれば(例えば、メソッドへのレイトバインディング現在の方法は実際に代理人です)。インライン化は、MethodBase.GetCurrentMethodがだまされる可能性がある方法ですが、それが唯一の方法かどうか疑問に思っていますか?

+0

これは、テールコールの最適化とは異なり、単にforループへの再帰呼び出しを書き換えます。メソッド* always *には、コードセキュリティと例外に必要なスタックフレームがあります。メソッドがインラインになると、呼び出し元メソッドの名前が取得されます。 GetCurrentMethodは非常に高価であり、単にメソッド名をコードに書き込むためにキャンドルを保持できないことに注意してください。インライン化の問題もそれ自身で解決されます。 –

+0

@Hans、x64のテールコールの最適化については、こちらをご覧ください:[link](http://www.hanselman.com/blog/ReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspx)あなたのコメントは立っているかもしれませんが、その例では再帰を見ていません。遅延結合シナリオでは、サロゲートは、代理への後続の呼び出しが再び反映する必要がないように、動的代理人を構築してキャッシュします。したがって、パフォーマンスは主な考慮事項ではありません。むしろ信頼性は(コード中のメソッド名の埋め込みは、メソッドの名前が変更された場合、信頼性問題の影響を受け易い)。 –

+0

私はちょうど私に起こりました。私は 'GetCurrentMethod'(信頼性がない)やコードにメソッド名を文字列として埋め込むことは必要ありません(自動的にタイプミスやリネームを処理しません)。代わりに、メソッドを呼び出す式を埋め込むことができます。しばらくの間、私はプロパティの参照のためにこれを行ってきました。同じテクニックをメソッドに適用することを考えるのがなぜそんなに長い時間がかかったのか分かりません。 –

答えて

2

いいえ - メソッドは実行時にインライン化されているか、実行時にインライン化されていません。

誰かが自分のランタイムを実装した場合、私は信じて、だまされることができます - MethodBase.GetCurrentMethodとして、最終的にこのつまるところは、RuntimeMethodHandleで宣言された:何でもできるカスタムランタイムでは、

[SecurityCritical] 
[MethodImpl(MethodImplOptions.InternalCall)] 
private static extern IRuntimeMethodInfo 
    _GetCurrentMethod(ref StackCrawlMark stackMark); 

を - 将来的には何もすることができます。現時点では、Microsoftランタイムが正しいメソッドを返さない唯一の方法は、コードがインライン化されている場合のみです。たとえば、モノを話すことはできません。しかし、常にそうであることに頼ることは、コードの一部を動作させるために常に存在する内部型の公開されたプライベートフィールドに頼っているようなものです。

私が試した(私はこれ以上心配しなくても)ほとんどの場合、プロファイリングの外で呼び出しメソッドを確実に識別できるようにする必要があることを正当化しようとすると、インラインメソッドの問題が常に発生します。

しかし、現実には、それらの方法について心配することはどれくらい重要ですか?

信頼性が非常に重要な場合は、IL-rewriterポストコンパイルを使用してロギングコールを注入します。これは必然的にメソッドを意識することができるため、インライン化が発生してもそれを覆すことができます(書き換えられたILが十分に大きくなってパフォーマンスが低下した場合など)。あるいは、自分自身を好きにならない場合は、PostSharpのようなAOPライブラリが順番に並んでいるかもしれません。

+0

私の質問は本当にインライン展開ではありません。インライン化は、 'MethodBase.GetCurrentMethod'がだまされることがあることを私が知っている単なる1つの方法です。私の質問は、 'MethodBase.GetCurrentMethod'をだますことができる(つまり、プログラマーが呼び出したメソッドとは異なるメソッドを特定する)方法があるかどうかです。 –

+0

さて、JITのインライン展開は唯一の方法ではない可能性があります。私の更新された答えが示すように、MSランタイムはインライン展開でしかないかもしれませんが、将来、他のランタイム知っている。特定の動作に頼らないことをお勧めします。そして実際にはあなたの定義を考えれば、開発者がどこに電話をかけるのか、実際にどこで終わるのかということについては、IL rewriterがこの動作を達成することができます。 –

関連する問題