問題タブ [disruptor-pattern]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - Java の LockSupport.parkNanos() に相当する Windows C++
Win7 x64 でこの関数と同じ機能を実装する必要があります。
最初に使用SwitchToThread()
しましたが、極端な条件下でデッドロックが発生するため、これは機能しません。私が見つけることができる唯一の代替手段はSleep()
、ミリ秒の解像度でしか機能しないため、これはパフォーマンスキラーである可能性が高く、LockSupport.parkNanos()
.
ナノ秒間隔でスレッドをスケジュールする Java の機能 (それが起こった場合) が疑わしいことがわかったので、スレッドが実行すると想定できるものを実装しました... スピン。ただし、これで問題が解決するかどうかはわかりません.Java関数が機能するにはJVMの介入が必要なように見えるため、避けられないことを遅らせているだけかもしれません。のソース コードはありませんparkNanos
。ネイティブの Sun ライブラリに実装されています。
呼び出しコードは次のようになります。
FWIW、LMAX の Disruptor パターンを C++ に移植しています。デッドロックは、あるスレッドが入っていSingleThreadedClaimStrategy::WaitForFreeSlotAt()
て別のスレッドが入っているときに発生していますBlockingWaitStrategy::WaitFor
(タイムアウトなし)。RingBuffer のサイズが 1、2、4、8 などのように小さい場合、デッドロックはより明白になります。
スレッドは通常のCreateThread
方法で作成されます。
編集:これを書いたときはかなり遅かったので、ここにもう少し情報があります。RingBuffer は__int64
s を保持します。1 つのプロデューサー スレッドと 1 つのコンシューマー スレッドがあります。Consumer スレッドは、Consumer が最後に消費したイベントのシーケンス番号を毎秒ポーリングする Timer スレッドも生成します。コンシューマーが進歩せず、プロデューサーも完了していない時点が来ます。Producer は、カウンタを公開するループを数億回実行するだけです。したがって、私の出力は次のようになります。
すべてが速度のために最適化されているリリース モードでのみ、実際に再現可能です。
java - ディスラプター:ジャーナリングの例
ジャーナリングのステップに関するディスラプターの最も一般的な(または推奨される)実装について興味がありました。そして、私の最も一般的な質問は次のとおりです。
- それが実際にどのように実装されているか(例によって)?
- JPAを使用するのは賢明ですか?
- どのDBが一般的に使用されていますか(ディスラプターを使用してプロジェクトをすでに実装しているコミュニティによって)?
- (EventProcessorsの)中間ハンドラーで使用するのが賢明なので、ビジネスロジックプロセスの前後ではなく、各メッセージの状態を保存する必要がありますか?
ちなみに(申し訳ありませんが、これはジャーナルの手順とは関係ありません)、eventHandlerプロセス中にRingBufferからメッセージを削除する正しい方法は何ですか(メッセージがデッド/期限切れであり、によって削除する必要があると仮定します)手順全体)。DeadLetterChannelパターンに似たものを考えていました。
乾杯!
java - メモリ内の大きなモデルと CQRS で Disruptor (LMAX) を使用する必要がありますか?
私たちのシステムは、パフォーマンス上の理由から、完全にメモリ (約 10 Gb) に保持される構造化モデル (いくつかの種類の関係を持つ約 30 の異なるエンティティ) を持っています。このモデルでは、3 種類の操作を行う必要があります。
- 1 つまたはいくつかのエンティティを更新する
- 特定のデータのクエリ (これには通常、何千ものエンティティを読み取る必要があります)
- 統計データの取得 (メモリ使用量、種類に対するクエリ数など)
現在のアーキテクチャはかなり標準的なもので、共有モデルを使用するサーブレット用のスレッドのプールがあります。モデル内には多くの同時コレクションがありますが、いくつかのエンティティが「よりホット」であり、ほとんどのスレッドがそれらを読み書きしたいため、まだ多くの待機があります。通常、クエリは書き込みよりもはるかに多くの CPU と時間を消費することにも注意してください。
モデルを単一のスレッドに保持し、可能なすべて (妥当性チェック、監査など) を別のコンシューマーのモデルから移動する Disruptor アーキテクチャに切り替える可能性を研究しています。
もちろん、最初の質問は次のとおりです。それは理にかなっていますか?
Secondo の質問: 理想的には、書き込み要求は読み取り要求よりも優先されるべきです。ディスラプターで優先順位を付ける最良の方法はどれですか? 私は2つのリングバッファについて考えていたので、優先度の低いものよりも優先度の高いものからより頻繁に読み取ろうとしました。
質問を明確にすることは、LMAX Disruptor の実際のコードよりもアーキテクチャに関するものです。
詳細を更新
データは複雑なドメインであり、多くの異なるタイプ (~20) の多くのエンティティ (>100k) が、多くの異なるコレクションを持つツリー構造でリンクされています。
通常、クエリでは、何千ものエンティティを走査して正しいデータを見つけます。更新は頻繁に行われますが、一度に 10 個のエンティティのようにかなり制限されているため、データ全体ではあまり変化していません (1 時間で 20% など)。
私はいくつかの予備テストを行いましたが、モデルを並行してクエリすることによる速度の利点は、時折発生する書き込みロックの遅延を上回るようです。
c# - ディスラプターの例が遅いのはなぜですか?
Stack Overflow question Disruptor.NET exampleからコード例を取得し、時間を「測定」するように変更しました。完全なリストは以下のとおりです。
出力は次のとおりです。
したがって、あるスレッドから別のスレッドにデータを渡すのに約 50 マイクロ秒かかります。でも全然速くない!「Disruptor の現在のバージョンは、1 秒あたり 100 万メッセージの速度で、スレッド間で最大 50 ns を実行できます。」したがって、私の結果は予想よりも 1000 倍遅くなります。
私の例の何が問題なのですか?どうすれば 50 ns の速度を達成できますか?
上記のプログラムを修正したところ、1 マイクロ秒の遅延が発生し、はるかに改善されました。disruptor
ただし、パターンの専門家からの回答を待っています。実際に 50 ns でデータを渡すことができることを証明できる例を探しています。
BlockingCollection
また、平均で 14 マイクロ秒を使用して同じテストを作成し、受信しました。これは、Disruptor
より高速であることを証明しています。
BlockingCollection の使用:
ディスラプターの使用:
BlockingCollection コード:
ディスラプター コード:
c# - 1 つのパブリッシャーと 4 つの並列コンシューマーを使用したディスラプターの例
この例ではhttps://stackoverflow.com/a/9980346/93647とここでは、なぜ私のディスラプターの例はとても遅いのですか? (質問の最後に)アイテムを公開するパブリッシャーが 1 人、消費者が 1 人います。
しかし、私の場合、消費者の仕事ははるかに複雑で、時間がかかります。したがって、データを並行して処理する 4 つのコンシューマーが必要です。
たとえば、プロデューサーが数字を生成する場合: 1,2,3,4,5,6,7,8,9,10,11..
consumer1 が 1,5,9 をキャッチし、consumer2 が 2,6,10 をキャッチし、consumer3 が 3,7,11 をキャッチし、consumer4 が 4,8,12... をキャッチします (正確にはこれらの数値ではありません。アイデアは、データを並行して処理する必要があるということです。どの特定の数値がどの消費者で処理されるかは気にしません)
実際のアプリケーションでは、消費者の作業はかなり高価であるため、これは並行して行う必要があることを覚えておいてください。マルチコアシステムの力を利用するために、消費者は異なるスレッドで実行されることを期待しています。
もちろん、4 つのリングバッファーを作成し、1 つのコンシューマーを 1 つのリングバッファーにアタッチすることもできます。このようにして、元の例を使用できます。しかし、それは正しくないだろうと私は感じています。おそらく、1 つのパブリッシャー (1 つのリングバッファー) と 4 つのコンシューマーを作成するのが正しいでしょう - これが私が必要としているものです。
Google グループの非常に似たような質問へのリンクを追加: https://groups.google.com/forum/#!msg/lmax-disruptor/-CLapWuwWLU/GHEP4UkxrAEJ
したがって、次の 2 つのオプションがあります。
- 1 つのリングで多数のコンシューマー (各コンシューマーは追加のたびに「ウェイクアップ」し、すべてのコンシューマーは同じ WaitStrategy を持つ必要があります)
- 多くの「1 つのリング - 1 つのコンシューマ」 (各コンシューマは、処理する必要があるデータでのみウェイクアップします。各コンシューマは独自の WaitStrategy を持つことができます)。
c# - ディスラプターの Next/Publish メソッドへのアクセスを同期する必要がありますか?
ディスラプターに精通している人には以下のコードで十分なので、完全なリストは提供していません。Next
問題は、メソッドの呼び出しPublish
がスレッドセーフかどうかです。以下の例のうち、正しいものはどれでしょうか? Attach
異なるスレッドから同時に呼び出すことができることに注意してください。そして、私には複数の消費者がいます。
例1. すべてをロックする:
例2. 次をロック:
例3. ロックなし
c# - disruptor-netを使用したコードはBlockingCollectionよりも低速です
Disruptorは、BlockingCollectionよりもはるかに高速であると想定されています。
私の前の質問で、なぜ私のディスラプターの例はとても遅いのですか?私は2つのテストを書きました。Disruptor
BlockingCollectionが約14マイクロ秒を費やしたのに対し、約1マイクロ秒(またはそれ以下)を費やしました。
そのため、プログラムで使用することにしましたが、実装すると、BlockingCollectionがまだマイクロ秒を費やしているのに、約マイクロ秒を費やしてDisruptor
いることがわかりました。Disruptor
50
14-18
プロダクションコードを「スタンドアロンテスト」に変更しましたが、Disruptor
それでも50マイクロ秒を費やしています。なんで?
簡略化したテストを以下に示します。このテストでは、2つのオプションがあります。最初のオプションはSleep for 1 ms
です。次にDisruptor
、配信に30〜50マイクロ秒を費やします。2番目のオプションは、アクティビティをシミュレートすることです。次にDisruptor
、配信に7マイクロ秒を費やします。BlockingCollection
14〜18マイクロ秒の結果で同じテスト。では、なぜDisruptorはBlockingCollectionよりも高速ではないのでしょうか。
私の実際のアプリケーションでは、 Disruptor
50マイクロ秒を費やして、多すぎるものを配信します。1マイクロ秒よりもはるかに速くメッセージを配信するはずです。
古いコード。今は無視する必要があります:
出力:
disruptor-pattern - ディスラプターのClaimStrategyバッファサイズを設定する方法
今私はdisruptorを使用しています、consumer-productorの簡単な例を取得します。それは完璧に動作しますが、buffersizeの意味がわかりません。どのサイズに設定する必要がありますか?
private static final int BUFFER_SIZE = 4;
BUFFER_SIZEの意味は何ですか?
java - ディスラプター:ゲーティングシーケンス
私はJavaでDisruptorを勉強しています。ゲーティングシーケンスの意味がわかりません。コア部分はリングバッファであり、すべてのバッファはシーケンス番号に関連付けられていることを私は知っています。