MSXML6 を使用して XML メッセージを継続的に解析し、準備された XSLT 変換を適用してテキストを生成するマルチスレッド サーバー C++ プログラムがあります。これを 4 つの CPU を搭載したサーバーで実行しています。各スレッドは完全に独立しており、独自の変換オブジェクトを使用します。スレッド間で COM オブジェクトが共有されることはありません。
これはうまく機能しますが、問題はスケーラビリティです。実行時:
- 1 つのスレッドで、スレッドごとに毎秒約 26 の解析 + 変換を取得します。
- 2 スレッドの場合、約 20/s/スレッドが得られます。
- 3 スレッド、18/s/スレッド。
- 4 スレッド、15/s/スレッド。
スレッド間で共有されるものは何もないので、ほぼ線形のスケーラビリティーを期待していたので、4 スレッドの方が 1 スレッドよりも 4 倍速くなるはずです。代わりに、2.3 倍しか速くなりません。
これは、古典的な競合の問題のように見えます。コード内で競合が発生する可能性を排除するために、テスト プログラムを作成しました。ドキュメントがスレッド間で共有されることはないため、不要なロックを回避するために、FreeThreadedDOMDocument の代わりに DOMDocument60 クラスを使用しています。キャッシュラインの偽共有の証拠を探しましたが、少なくとも私のコードには何もありませんでした。
別の手がかりとして、コンテキスト スイッチ レートは各スレッドで 15k/s を超えています。原因は、COM メモリ マネージャーまたは MSXML 内のメモリ マネージャーであると推測しています。おそらく、メモリの割り当て/割り当て解除ごとに取得および解放する必要があるグローバルロックがあります。この時代に、メモリ マネージャーがマルチスレッドのマルチ CPU シナリオで適切にスケーリングするように記述されていないとは信じられません。
この競合の原因や解消方法を知っている人はいますか?