2

C++ アプリケーションの DOM でクライアントが何百もの特定の種類のオブジェクト「Foo」を作成しているというパフォーマンスの問題があります。各 Foo インスタンスには、独自のスレッドを持つ独自の非同期作業キューがあります。明らかに、それはスケーリングしません。

ワーク キュー間でスレッドを共有する必要がありますが、車輪の再発明はしたくありません。XP をサポートする必要があるため、Vista/Win7 スレッド プールを使用できません。各キュー アイテムを処理するために必要な作業には、マルチスレッド COM アパートメントでの COM 呼び出しの作成が含まれます。XP スレッド プールのドキュメントには、スレッド ワーカー関数のコールバックで MTA アパートメントを使用して CoInitializeEx() を呼び出しても問題ないと書かれています。テストアプリを作成し、これが機能することを確認しました。WorkItem コールバック関数で CoInitializeEx/CoUninitialize ペアを使用する場合と使用しない場合で、アプリを 100 万回反復実行させました。CoInit* 呼び出しで 35 秒、呼び出しなしで 5 秒かかります。これは、私のアプリケーションにとってオーバーヘッドが多すぎます。スレッド プールはプロセスごとであり、サード パーティのコードは自分のプロセスで実行されるため、そうではないと想定しています。

以上のことから、Win32 スレッド プールを使用する方法はありますか? 何か足りないのでしょうか、それとも XP スレッド プールは高パフォーマンスの COM アプリケーションには役に立たないのでしょうか? 独自のスレッド共有システムを作成する必要がありますか?

4

2 に答える 2

1

CoInitializeEx()をスレッドごとに1回実行するのは安全ではなく、CoUninitialize()を実行するのは安全ではないと思います。

CoUninitializeを呼び出さずにスレッドが終了した場合、Windowsはクリーンアップします。終了しなかった場合、スレッドがクラッシュまたは中止されたときにクリーンアップが行われないため、これが機能することがわかっています。

したがって、このハッキングが問題を引き起こす可能性がある唯一の方法は、誰かがSTAアパートを必要とする作業項目をキューに入れようとしたことです。

私はそれのために行きたくなるでしょう。

于 2010-02-04T01:37:37.853 に答える
1

時間がかかっていることを確認しましたか?つまり、CoInitializeEx() の呼び出しですか? タスクごとに 1 回 CoInitialize を呼び出す必要はありません。また、スポーンするスレッドの数も言いません。つまり、デュアルコアで実行していて、作業が CPU 集中型である場合は、2 倍以上のスピードアップを期待しないでください。作業が CPU 集中型でない場合は、いくつかのスレッドを待機しています。リソース (メモリ、ディスク、ネット) とスピードアップも同様に制約され、そのリソースに対して保持されているロックがあるとおそらく悪化します。

Visual Studio 2010 を使用できる場合は、Parallel Pattern Library と Asynchronous Agents Library を参照してください。これを作成するコードを少なくするのに役立つツールがいくつかあります。

できない場合は、少なくともそのスレッドで COM が初期化されているかどうかを表すトークンを TLS に配置し、このトークンの存在を使用して、不要なときに CoInitialize への呼び出しをバイパスすることができます。

于 2010-02-04T14:31:39.450 に答える