0

MSXML6 を使用して XML メッセージを継続的に解析し、準備された XSLT 変換を適用してテキストを生成するマルチスレッド サーバー C++ プログラムがあります。これを 4 つの CPU を搭載したサーバーで実行しています。各スレッドは完全に独立しており、独自の変換オブジェクトを使用します。スレッド間で COM オブジェクトが共有されることはありません。

これはうまく機能しますが、問題はスケーラビリティです。実行時:

  1. 1 つのスレッドで、スレッドごとに毎秒約 26 の解析 + 変換を取得します。
  2. 2 スレッドの場合、約 20/s/スレッドが得られます。
  3. 3 スレッド、18/s/スレッド。
  4. 4 スレッド、15/s/スレッド。

スレッド間で共有されるものは何もないので、ほぼ線形のスケーラビリティーを期待していたので、4 スレッドの方が 1 スレッドよりも 4 倍速くなるはずです。代わりに、2.3 倍しか速くなりません。

これは、古典的な競合の問題のように見えます。コード内で競合が発生する可能性を排除するために、テスト プログラムを作成しました。ドキュメントがスレッド間で共有されることはないため、不要なロックを回避するために、FreeThreadedDOMDocument の代わりに DOMDocument60 クラスを使用しています。キャッシュラインの偽共有の証拠を探しましたが、少なくとも私のコードには何もありませんでした。

別の手がかりとして、コンテキスト スイッチ レートは各スレッドで 15k/s を超えています。原因は、COM メモリ マネージャーまたは MSXML 内のメモリ マネージャーであると推測しています。おそらく、メモリの割り当て/割り当て解除ごとに取得および解放する必要があるグローバルロックがあります。この時代に、メモリ マネージャーがマルチスレッドのマルチ CPU シナリオで適切にスケーリングするように記述されていないとは信じられません。

この競合の原因や解消方法を知っている人はいますか?

4

3 に答える 3

2

ヒープベースのメモリ マネージャー (基本的な malloc/free) が単一のミューテックスを使用することはかなり一般的です。これにはかなりの理由があります。ヒープ メモリ領域は単一の一貫したデータ構造です。

この制限のない代替メモリ管理戦略 (階層アロケータなど) があります。MSXML で使用されるアロケータのカスタマイズについて調査する必要があります。

または、マルチスレッド アーキテクチャから、MSXML ワーカーごとに個別のプロセスを使用するマルチプロセス アーキテクチャへの移行を検討する必要があります。MSXML ワーカーは文字列データを入力および出力として受け取るため、シリアル化の問題はありません。

要約すると、マルチプロセス アーキテクチャを使用すると、問題により適したものになり、スケーリングも向上します。

于 2008-11-28T19:20:25.343 に答える
1

MSXMLは、ヒープ管理でグローバルロックを使用するBSTRを使用します。数年前、大規模なマルチユーザーアプリで多くの問題が発生しました。

アプリでのXMLの使用を削除しました。これを実行できない可能性があるため、代替のXMLパーサーを使用する方がよい場合があります。

于 2008-11-29T00:10:39.893 に答える
1

答えてくれてありがとう。私は最終的に2つの提案を組み合わせて実装しました。

C# で COM+ ServicedComponent を作成し、COM+ の下で別のサーバー プロセスとしてホストし、XSLCompiledTransform を使用して変換を実行しました。C++ サーバーは、COM を使用してこの外部プロセスに接続し、それに XML を送信して、変換された文字列を取得します。これにより、パフォーマンスが 2 倍になりました。

于 2009-02-09T16:30:28.603 に答える