11

私は Disruptor フレームワークを使用して、一部のデータに対して高速なリードソロモン エラー修正を実行しています。これは私のセットアップです:

          RS Decoder 1
        /             \
Producer-     ...     - Consumer
        \             /
          RS Decoder 8 
  • プロデューサは、2064 バイトのブロックをディスクからバイト バッファに読み取ります。
  • 8 つの RS デコーダ コンシューマは、リードソロモン エラー訂正を並行して実行します。
  • コンシューマはファイルをディスクに書き込みます。

ディスラプター DSL 用語では、セットアップは次のようになります。

        RsFrameEventHandler[] rsWorkers = new RsFrameEventHandler[numRsWorkers];
        for (int i = 0; i < numRsWorkers; i++) {
            rsWorkers[i] = new RsFrameEventHandler(numRsWorkers, i);
        }
        disruptor.handleEventsWith(rsWorkers)
                .then(writerHandler);

ディスク出力コンシューマー (no part)がない.then(writerHandler)場合、コンシューマーを追加するとすぐに測定されたスループットは 80 M/s です。/dev/null従属消費者の場合、パフォーマンスは 50 ~ 65 M/s に低下します。

Oracle Mission Control でプロファイリングしたところ、CPU 使用率のグラフは次のようになりました。

追加のコンシューマーなし: 追加の消費者なし

追加のコンシューマ: 追加のコンシューマーあり

グラフのこの灰色の部分は何ですか? また、どこから来ているのでしょうか? スレッドの同期に関係していると思いますが、Mission Control には、そのような遅延や競合を示す他の統計は見つかりません。

4

2 に答える 2

2

あなたが示したことに基づいて、ここで2つの可能性を見ることができます。いずれかまたは両方の影響を受ける可能性があります。両方をテストすることをお勧めします。1) IO 処理のボトルネック。2) 複数のスレッドがバッファに書き込む際の競合。

IO処理

表示されたデータから、IO コンポーネントを有効にするとすぐにスループットが低下し、カーネル時間が増加することがわかりました。これは、コンシューマー スレッドが書き込みを行っている間の IO 待機時間である可能性があります。呼び出しを実行するためのコンテキスト スイッチは、write()何もしない場合よりもはるかにコストがかかります。あなたDecoderの は現在、消費者の最大速度に制限されています。この仮説をテストするために、write()呼び出しを削除できます。つまり、出力ファイルを開き、出力用の文字列を準備し、書き込み呼び出しを発行しないだけです。

提案

  • コンシューマーで呼び出しを削除してみて、write()カーネル時間が短縮されるかどうかを確認してください。
  • 単一のフラット ファイルに順番に書き込んでいますか - そうでない場合は、これを試してください
  • endOfBatchIO が可能な限り効率的にまとめられるように、スマート バッチ処理 (つまり、フラグまでバッファリングしてから単一のバッチに書き込む) を使用していますか?

複数のライターの競合

あなたの説明に基づいて、あなたDecoderの s はディスラプターから読み取ってから、まったく同じバッファーに書き戻していると思われます。これにより、メモリへの書き込みを行う CPU で複数のライター (別名、競合) の問題が発生します。私が提案することの 1 つは、2 つのディスラプター リングを用意することです。

  1. Producer#1に書き込みます
  2. Decoder#1 から読み取り、RS デコードを実行し、結果を #2 に書き込みます
  3. Consumer#2 から読み取り、ディスクに書き込みます

RB が十分に大きいと仮定すると、これにより、メモリをきれいにウォークスルーできるはずです。

ここで重要なのは、Decoderスレッド (別のコアで実行されている可能性があります) が、Producer. これを行うコアが 2 つだけの場合、ディスク速度がボトルネックでない限り、おそらくスループットが向上します。

サンプルコードを含め、これを実現する方法をより詳細に説明しているブログ記事がここにあります。http://fasterjava.blogspot.com.au/2013/04/disruptor-example-udp-echo-service-with.html

他の考え

  • WaitStrategy何を使用しているか、マシンに搭載されている物理 CPU の数などを知ることも役に立ちます。
  • WaitStrategy最大のレイテンシーが IO 書き込みであることを考えると、別のサーバーに移行することで、CPU 使用率を大幅に削減できるはずです。
  • かなり新しいハードウェアを使用していると仮定すると、このセットアップだけで IO デバイスを飽和させることができるはずです。
  • また、適切なパフォーマンスを実現するには、ファイルが異なる物理デバイス上にあることを確認する必要があります。
于 2015-02-24T12:01:52.150 に答える