12

ここで頭を悩ませています。アプリケーションの WPF コンポーネントのパフォーマンスの問題を調査しています。

私たちの .net アプリケーションは非常に大きく、ほぼ完全に Windows フォームです。新しいイニシアチブの一環として、コア コンポーネントの 1 つをリッチな WPF UI で書き直しました。多くの WinForms<-->WPF 相互運用がこのことと一緒に行われています。

ANTS プロファイラーで遅い操作をプロファイリングすると、関数 UnsafeNativeMethods.IntGetMessageW 内で多くのアクティビティが発生していることがわかります。ANTS は、すべてのビジネス ロジックと wpf レンダリングを組み合わせたものと同じくらい多くの CPU アクティビティをレポートします。サイクルを使用しているその関数のマネージ コード ダウンラインはありません。

私は win32 プログラミングに特に精通しているわけではありませんが、そのコンテキストでのメッセージ ループの基本は知っています。ここで見ているのは、手動で行うものではありません。コードのどの時点でも、基になるメッセージループ自体や、WPF ディスパッチャーでアクセスできるより複雑なものと直接対話していません。

ここで問題となっている WPF コンポーネントは Window から継承して記述されており (つまり、単なるコントロール/ユーザー コントロールではありません)、このコンポーネントの古い WinForms バージョンで ShowDialog を呼び出していた上位レベルのロジックから ShowDialog を使用して表示します。WPF コンポーネント内で使用した WindowsFormsIntegrationHost コントロールがいくつかあり、WPF で書き換えることができなかった一部の既存の部分との互換性を維持します。

私はこれを何日も調査してきましたが、続けるべきことがたくさん見つかりませんでした。入力メッセージ (マウスとキーボード) について話している漠然と関連する投稿を見つけ続けていますが、それを確認するために何ができるかわかりません。私はすでにコードを解体して、可能なすべてのマウス/キーボード操作を削除しようとしました。

主に、このコード行が完全に分離されており (実際に私たちのコードから来ていると指摘できるものの親または子ではない)、それが何をしているかについて完全に不透明であるため、どこにでも行くのに苦労しています。

ここに到達するための呼び出しのパスを示す ShowDialog 関数の ANTS 呼び出しグラフの画像を次に示します。 代替テキスト

これは WPF の一部として実行しなければならないこと (WPF で記述した他のコンポーネントはこの動作を表示しませんが) である可能性があること、またはこれは ANTS プロファイラーの非常に奇妙なバグであることを完全に認識していますが、この時点で、何らかの方法で確認する必要があります。誰かがここで何が起こっているか、または何が起こっているのかを教えてくれたり、自分でそれを理解できる方法を教えてくれたりしたら、あらゆる種類の良いカルマをあなたに向けます.

更新:以下のいくつかの議論に応えて、ANTSからの別のビューがあります-これは、私が抱えている混乱をよりよく示しています(これは、「CPU時間」モードのANTSビューです)。私は急いでコードの一部を検閲しましたが、システム関連の機能は一切検閲しませんでした:

代替テキスト

ご覧いただきありがとうございます。

4

4 に答える 4

5

はい、これは正常です。GUI アプリは常にGetMessageW() を実行しており、Windows がメッセージを送信するのを待っています。実際にこれを行っているのは CPU サイクルを消費しているのではなく、ある種の UI イベントが通知されるまで内部同期オブジェクトでブロックされているだけです。

もちろん、これにより UI アプリのプロファイリングが難しくなります。アプリのサブコンポーネントをテストする単体テストが本当に必要になります。

于 2010-11-08T20:19:37.113 に答える
3

アプリケーションをプロファイリングするときは、メソッドで費やされた時間と消費されたCPUサイクルを区別する必要があります。多くのプロファイリングツールは、メソッドに費やされた全体的な時間を示します-何かの場合、それGetMessageWはかなり長くなるでしょう。GUIアプリケーションのメインスレッドのすべてのアクティビティは、そのメソッド内で発生するように見えます。これは必ずしも問題ではありませんが、これは単に同期オブジェクトを待機しているメインメッセージポンプであり、実際にはサイクルを消費していない可能性があります。

まず、ANTSプロファイラーのサンプリング機能を使用して、最も頻繁に呼び出されるメソッドを特定し、それらを最も多くのCPUサイクルを消費しているメソッドに関連付けることをお勧めします。それが済んだら、アプリケーションをインストルメント化してさらに詳しく調べ、CPUを最も集中的に使用する場所のコールグラフがどのように見えるかを判断します。

最初に自分のコードを疑うことから始めるべきです。WPFやWin32インフラストラクチャのようなものが、パフォーマンスの低下やCPU使用率の上昇の原因となることはめったにありません。おそらく、問題は実装のどこかにあります。これは、CPUサイクルがプログラムのどこで費やされているかを全体的に把握するのに役立ちます。

プロファイラーの機能を最も効果的に学習するためにも、ある程度の時間を費やすことをお勧めします。プロファイラーは、彼らがあなたに見せようとしていることが何であるかを理解するまで、洗練された混乱するツールになる可能性があります。RedGateからのリンクされたチュートリアルは、まだ行っていない場合は、開始するのに適した場所です。たとえば、タイムラインビューは、実際には、CPUの高いアクティビティが発生している場所を確認し、実行されたコードのセグメントに分析を限定するのに適した場所です。

代替テキスト

コールグラフは、コードの最も高価な領域にドリルダウンするのに役立つため、ANTSのもう1つの便利なツールです。重要なのは、全体の時間だけでなく、全体のコストを見ていることを確認することです。

代替テキスト

于 2010-11-08T20:30:15.953 に答える
1

同じ問題に関する情報を検索しているときにこれを見つけました。私が知っていることを追加し、それが役立つかどうかを確認します。

私はWinXPボックスで実行しています-WPFフレームワークはXPよりもVistaとWin7に統合されています。これの一部は、WPFがXPデスクトップ内ではなく、XPデスクトップの「上」で実行される方法が原因である可能性があります。

WinFormsやその他のコードを使用せずに、純粋なネイティブWPFアプリケーションを実行しています。

私は、ウィンドウをスクロールするだけで100%のCPUを消費し、それを実行しているときに途切れることになる理由を特定しようとして、これに遭遇しました。

AQtimeパフォーマンスプロファイラーを実行すると、IntGetMessageWがその100%のCPU使用率の大部分を占めていることがわかります。これは、IntGetMessageWがメッセージを待機しているためではなく、関数が実際に実行していることによるものです。

私がまだ調べていないことの1つは、IntGetMessageWが高速なメソッドではなかった可能性があり、WPFが単にそれを使いすぎている可能性があることです。WPFのデータバインディングがネイティブのWin32メッセージポンプを使用して、WPF内の依存関係プロパティを更新する可能性があります。その場合は、ウィンドウのバインディングが多すぎる可能性があります。

于 2010-12-15T21:30:33.027 に答える
0

メッセージ ポンプが大量にポンピングされているようです。メッセージ キューがどのような種類のメッセージで満たされているかを確認するのは興味深いことです。ウィンドウで Spy++ を使用して、何が起こっているかを確認できますか?

編集

私は問題を誤解しました。

Hans Passant の言うとおりです。あなたのプログラムは、何らかのイベントが処理されるのを GetMessage で待機しているだけです。

于 2010-11-08T20:19:33.800 に答える