2010-11-18 10 views
2

私はまだC++/cliをかなり新しくしていますが、私が何かを書いているときは、 。例えば、LARGE_INTEGERやstd :: vectorをマネージクラスのメンバとして追加することはできませんが、マネージドメソッドの途中で使用することはできますが、マネージドメソッドとアンマネージ間の遷移を作成するかどうかはわかりませんランタイム。どのような移行が行われるのか、移行のコストをどのように測定するのか管理対象/非管理対象間の移行を認識してコストを測定するC++/cli

私に起こる可能性の1つは、ウィンドウ内に「管理されていない状態への移行」と「管理された状態への遷移」があることです。ブレークポイントを置くことができるシンボルがありますか?私はそれぞれの移行を見ることができますか?実行時に各トランジションを表示するためにビジュアルスタジオを取得する方法はありますか?

遷移が多い場合のinpactを測定するには、xperfで見ることのできるWindowsイベント、またはperfmonで見ることのできるパフォーマンスカウンタに対応するイベントトレースがありますか?

答えて

6

「管理されていないランタイム」は、少し矛盾しています。アンマネージコードは、仮想マシンでは実行されません。さらに、管理対象ランタイム自体がアンマネージドコードです。 CLRと標準ライブラリだけでなく、一般的にコードに興味があると思いますが、最終的にはすべてがネイティブコードですが、CLR JITによって作成されたものもあれば、ネイティブコンパイラによって作成されたものもあります最終的には。 .NET例外とネイティブ例外の両方に共通の例外処理モデル(SEH)もあります(正確には、.NETはOS提供の例外モデルを使用しています)。

JITが実行された後、単純な関数呼び出しであるため、管理されていないトランジションはほとんどありません(アンマネージコードはネイティブライブラリのアドレス空間にあるため、 JITコンパイルされたマネージコードは、JITが所有する動的アドレス空間にあります)。逆方向は、呼び出し命令が呼び出される前に作成されているため、(関数ポインタを介して)間接呼び出しでなければならないため、やや複雑です。しかし、それはまだJITコンパイルされたコードに直接的なポインタであり、ブレークポイントを置くことができるunmanaged-> managed thunkではありません。実際には、関数ポインタはおそらくJIT自体を指し始めます。JIT自体は、どのメソッドが呼び出されているかを調べ、コンパイルし、関数ポインタを更新し、最後に呼び出されたかのように最後に末尾呼び出しを行います。

これはC++ interopの魔法です。また、管理されていない管理されていない遷移も本当に心配する価値がないことを意味します。どのコードパスが高価であるかを調べ、管理コードと非管理コード間の呼び出しであることが判明したら、それを最適化します。しかし、管理された/管理されていない遷移をランダムに探すのではない。

ここで、管理対象/非管理対象のすべての移行を検索する理由があります。たとえば、ガベージコレクタはマネージコードを実行しているスレッドを中断することができます(実際に実行されているコードはネイティブコードですが、GCはJITで使用されるメモリ空間内にあるためそのコードを識別できます)。スタック変数は、任意の与えられた命令ポインタにおいて到達可能なオブジェクトである)。ですから、特定のスレッドがガベージコレクションによって決して停止されないようにしたい場合は、そのスレッドで実行される関数の管理されていない管理されたすべての遷移を取り除いて除去する必要があります。ブレイクポイントを置く場所があったとしても、ブレイクポイント注入は適切なアプローチではありません。これは、実際に実行されたトランジションを捕捉するだけであり、条件付きではありません。

+0

非常に興味深い。実行時にJITedマネージコードからネイティブコードを呼び出すことは不可視です(ただし、スタックに含まれている必要があるかもしれませんが)。 –

0

プロファイラは、あなたに答えを与えることができるものです。 VS2010プロファイラを使用して遷移を測定できます。

ETWトレースを使用することもできますが、分析するのはずっと難しくなります。 PerfMonitorはETWトレースに役立ちます。

FYIでもVS2010プロファイラはETWトレースのみを使用しますが、それを提示する方が良い方法です。

関連する問題