11

次は正しいですか?

  • 各エントリを複数の方法(io操作またはアノテーション)で処理する必要がある場合、ディスラプターパターンは、競合することなく複数のコンシューマーを使用して並列化できるため、並列パフォーマンスとスケーラビリティが向上します。
  • 逆に、ワークスティーリング(つまり、エントリをローカルに保存し、他のスレッドからエントリを盗む)は、各エントリを単一の方法でのみ処理する必要がある場合、ディスラプターパターンでエントリを複数のスレッドにばらばらに分散すると競合が発生するため、並列パフォーマンスとスケーラビリティが向上します。

(そして、複数のプロデューサー(つまりCAS操作)が関与している場合、ディスラプターパターンは他のロックレスマルチプロデューサーマルチコンシューマーキュー(ブーストなど)よりもはるかに高速ですか?)


私の状況の詳細

エントリを処理すると、いくつかの新しいエントリが生成される可能性があり、それらも最終的に処理する必要があります。パフォーマンスが最優先され、FIFO順に処理されるエントリが2番目に優先されます。

現在の実装では、各スレッドはローカルFIFOを使用し、そこで新しいエントリを追加します。アイドルスレッドは、他のスレッドのローカルFIFOから作業を盗みます。スレッドの処理間の依存関係は、ロックレスで機械的に同情的なハッシュテーブル(書き込み時のCAS、バケットの粒度)を使用して解決されます。これにより、競合はかなり少なくなりますが、FIFOの順序が崩れることがあります。

ディスラプタパターンを使用すると、FIFOの順序が保証されます。しかし、エントリをスレッドに分散すると、作業を盗むローカルFIFO(各スレッドのスループットはほぼ同じ)よりもはるかに高い競合(読み取りカーソルでのCASなど)が発生しませんか?


私が見つけた参考文献

ディスラプターに関する標準テクニカルペーパー(第5章+第6章)のパフォーマンステストは、ばらばらの作業分散をカバーしていません。

https://groups.google.com/forum/?fromgroups=#!topic/lmax-disruptor/tt3wQthBYd0は、ディスラプターとワークスティーリングについて私が見つけた唯一のリファレンスです。共有状態がある場合、スレッドごとのキューは劇的に遅くなると述べていますが、詳細や理由については説明していません。この文が私の状況に当てはまるとは思えません。

  • ロックレスハッシュテーブルで解決されている共有状態。
  • 消費者間でエントリをばらばらに配布する必要があります。
  • 作業の盗用を除いて、各スレッドはローカルキューでのみ読み取りと書き込みを行います。
4

1 に答える 1

14

更新-パフォーマンスを最大化するためのボトムライン:ディスラプターとワークスティーリングの慣用的な構文の両方を記述してから、ベンチマークを行う必要があります。

私にとって、その違いは主にメッセージとタスクの焦点の違いにあり、したがって問題の考え方にあると思います。問題を解決してみてください。タスクに重点を置いている場合は、Disruptorが最適です。問題がメッセージに焦点を合わせている場合は、作業の盗用などの別の手法に適している可能性があります。

  • 実装がメッセージに焦点を合わせている場合は、ワークスティーリングを使用します。各スレッドはメッセージを取得し、それを最後まで実行できます。HTTPサーバーの例-各インバウンドhttpリクエストにはスレッドが割り当てられます。このスレッドは、リクエストの開始から終了までの処理に重点を置いています。リクエストのログ記録、セキュリティコントロールの確認、vhostルックアップの実行、ファイルのフェッチ、応答の送信、接続の終了です。

  • 実装がタスクに焦点を合わせている場合は、 disruptorを使用します。各スレッドは、処理の特定の段階で機能します。別の例:タスクフォーカスの場合、処理はステージに分割されるため、ロギングを行うスレッド、セキュリティ制御用のスレッド、仮想ホストルックアップ用のスレッドなどがあります。各スレッドはそのタスクに焦点を合わせ、パイプライン内の次のスレッドに要求を渡します。ステージは並列化できますが、全体的な構造は特定のタスクに焦点を合わせたスレッドであり、スレッド間でメッセージを渡します。

もちろん、それぞれのアプローチに合わせて実装を変更することもできます。

あなたの場合、Disruptorを使用したい場合は、問題の構造を変えます。一般に、単一のスレッドに状態を所有させ、すべてのタスクをその作業スレッドに渡すことで共有状態を排除します。このような多くの図については、SEDAを検索してください。これには多くの利点がありますが、繰り返しになりますが、実際には実装に依存します。

もう少し冗長性:

  • ディスラプター-ステージの厳密な順序付けが必要な場合に非常に役立ちます。すべてのタスクが一貫した長さである場合の追加の利点。たとえば、外部システムでのブロッキングがなく、タスクごとの処理量が非常に似ています。このシナリオでは、すべてのスレッドがシステム全体で均等に機能すると想定できるため、N個のメッセージを処理するようにN個のスレッドを配置します。Disruptorは、スレッドがステージを処理するSEDAのようなシステムを実装するための効率的な方法だと思います。もちろん、単一のステージと複数の並列ユニットが各ステージで同じ作業を実行するアプリケーションを作成することもできますが、これは私の見解では実際には重要ではありません。これにより、共有状態のコストを完全に回避できます。
  • 作業の盗用-タスクの期間が異なり、メッセージ処理の順序が重要でない場合にこれを使用します。これにより、空きですでにメッセージを消費しているスレッドが別のタスクキューから進行を続けることができます。このように、たとえば10個のスレッドがあり、1個がIOでブロックされている場合でも、残りは処理を完了します。
于 2013-03-12T07:45:50.173 に答える