2011-11-07 12 views
7

私は、マルチスレッドを頻繁に使用するパフォーマンスクリティカルな.NETアプリケーションを作成しています。 Visual Studioのパフォーマンス・プロファイラを使用して多量のマルチスレッドアプリケーションのプロファイリング/最適化

、独占サンプルでトップの機能は以下のとおりです。

WaitHandle.WaitAny() - 14.23パーセント

@[email protected]から7.76パーセント

Monitor.Enterから5.09パーセント

基本的には、私のトップ3の関数は、スレッドプリミティブで動作しています。私の仕事/処理ルーチンはかなり小さく、パフォーマンスを向上させようとしています。私はかなり頻繁にそれらを見直しているが、関係するアルゴリズムはかなり健全であると私は信じる。

私の質問は以下のとおりです。

  • CPUサンプルの14.23パーセントは、これらの方法である場合 - すなわち、単に他のスレッドを待っている、これらのサンプルのほとんどのために効果的に「アイドル」CPUのですか?または、プロファイルトレースの一部として表示されていないスレッド待ちのアイドル部分[これら3つの同期方法のすべてのオーバーヘッドの合計は27.08%です。しかし、これらの結果は、私がさらにためになるはずですいくつかの特定のボトルネックや技法を示し行う、(私はこれがほとんどアイドル状態であることを推測することができますが、この1してくださいへの回答の背後にあるいくつかのまともな参考資料をいただければ幸いです)私は私のロックスキームを検討している
  • 最適化?
  • WaitAnyは特に不良ですか?特定のキューオブジェクトが読み書き可能であるかどうかを確認するために大量に使用しますが、同時にアボートフラグもチェックします。それを行う良い方法はありますか?
+0

あなたがそれらのプリミティブを使用する方法かもしれません。 –

+0

@Henk - 確かに、自分のアルゴリズムを見直して、スキームをロックすると言うことで言い訳しようとしました –

+0

@KierenJohnstone VS 2010をお持ちの方は、これに並行プロファイラ/ビジュアライザを使用してください。 –

答えて

4

あなたのCPUはスレッドがWaitHandle.WaitAnyMonitor.Enterのときにアイドル必ずしもではありません。待機中のスレッドのはアイドルですが、おそらく他のスレッドが実行中です。これは特にMonitor.Enterの場合に当てはまります。スレッド上でスレッドがブロックされている場合、そのロックを持つスレッドがアイドル状態ではなくコードを実行していることを期待します。

また、スレッドがWaitAnyをキューから読み取っている場合、そのキューには何も格納されていない可能性があります。それは消費者向けコードのパフォーマンス上の問題ではありません。プロデューサーが物事を十分に速くキューに入れていないことを意味します。今は、プロデューサーが遅いか、データが十分に速く到着しないためです。

あなたはそれはあなたのように見えない、より速く、それがで来ることができるよりも、データを処理している場合は、パフォーマンス上の問題を抱えています。確かに消費者側ではない。

キューイングのためにWaitAnyを使用している限り、私はBlockingCollectionと、TryAdd(T, Int32, CancellationToken)のような取り消しトークンを取るメソッドを使用することをお勧めします。キャンセルトークンに変換すると、マルチスレッドキューイングコードが本当に単純化されました。

+0

ありがとう私は確かにそのコレクションをチェックアウトします。私が知っている全体的なCPU使用量では、スレッドが待機中であることを知っています。他のユーザーがビジー状態になっているかもしれませんが、そこにキャプチャされたサンプルがアイドル状態でキャプチャされたスレッドとしてカウントされていたり、 「待っている」? –

+0

また、私は生産だけでなく消費もしています。プロダクションコードはこのプロファイルトレースに含まれていました。私はその後、トップの近くでプロダクションコードを見たいと思うでしょうか? –

+0

@Kieren:サンプルが(WaitAnyまたはMonitor.Enter'で)スレッドアイドルを示している場合、私はそれが本当にアイドルであることを期待します。プロファイリングオーバーヘッドが統計から削除されることが予想されます。あなたが見たいと思う限り、私はあなたのアプリケーションについて十分に知りません。ネットワークストリームやディスクファイルなどからデータを待っている場合、プロデューサもアイドル状態になる可能性があります。 –

4

プロファイリング統計はは、スレッドがブロックされた時間は含まれていません。

サンプリング・ベースのプロファイラ基本的に非アイドルサイクル(1,000,000を言う)すべてのXの後に戻って報告するために、各コアを要求します。コアが報告するたびに、プロファイラは現在のコールスタックを覚えています。プロファイリング結果は、プロファイラが記録したコールスタックから再構築されます。

プロファイリングの結果から、コアが作業していた時間の14.23%で、WaitHandle.WaitAnyの命令が実行されていたことがわかります。プログラムがCPUにバインドされている場合、WaitAny部分を最適化する(たとえば、別のプリミティブを使用する)ことは、パフォーマンスに重大な影響を与える可能性があります。しかし、プログラムがではなく、 CPUバウンドで、サーバー、ディスク、別のプロセスまたは他の外部入力で待機する時間が大半であれば、WaitAny関連のコードを最適化することはあまり役に立ちません。

次の手順では、プログラムのCPU使用率を把握する必要があります。また、プログラム内のスレッドがどのように時間を費やすかを理解するのに役立つ、並行処理ビジュアライザに注意してください。

+0

プログラム全体が〜70%のCPUを使用しているので、私はBlockingCollection JimのようなWaitAnyの代替案を検討します。 –

+0

Hey Kieren、これに関する最新情報は?最終的にどのようにCPU消費量を改善しましたか? –

関連する問題