11

私のアプリケーションには、独自のスレッドで情報を処理するサービスがいくつかあります。それらが完了すると、次のサービスにメッセージを投稿し、次のサービスは独自のスレッドで作業を続けます。メッセージの引き渡しは、LinkedBlockingQueue を介して行われます。通常、ハンドオーバーには 50 ~ 80 マイクロ秒かかります (キューにメッセージを入れてからコンシューマーがメッセージの処理を開始するまで)。最も重要なサービスのハンドオーバーを高速化するために、ブロッキング アプローチの代わりにビジー スピンを使用したいと考えました (12 個のプロセッサ コアがあり、これらの重要なサービスに 3 個を割り当てたいと考えています)。だから.. LinkedBlockingQueue を ConcurrentLinkedQueue に変更しました

そしてやった

for(;;)
{
 Message m = queue.poll();
 if( m != null )
  ....
}

その結果、最初のメッセージ パスに 1 マイクロ秒かかりますが、次の 25 回のハンドオーバーで遅延が増加し、500 マイクロ秒に達し、その後、遅延が突然 1 マイクロ秒に戻り、増加し始めます。レイテンシが 1 マイクロ秒で開始し、500 マイクロ秒で終了する 25 回の繰り返しのサイクル。(メッセージは毎秒約 100 回渡されます)

平均レイテンシが 250 であるため、私が求めていたパフォーマンスの向上とはまったく異なります。

また、ConcurrentLinkedQueue の代わりに LMAX Disruptor リングバッファを使用しようとしました。そのフレームワークには、ビジー スピンの実装とまったく異なるキューの実装で独自のビルドがありますが、結果は同じでした。だから、キューや私が何かを悪用したせいではないことは確かです..

質問は..ここで一体何が起こっているのですか? この奇妙なレイテンシ サイクルが表示されるのはなぜですか?

乾杯!!

4

4 に答える 4

1

私の知る限り、スレッド スケジューラは、このスレッドが CPU をかなり集中的に使用していることを検出した場合、スレッドを意図的に長時間一時停止して、異なるスレッド間で CPU 時間をより公平に分配することができます。LockSupport.park()キューが空になった後にコンシューマーに追加し、メッセージを追加した後にプロデューサーに追加してみてくださいLockSupport.unpark()。レイテンシーの変動が少なくなる可能性があります。ただし、ブロッキングキューと比較して実際に優れているかどうかは大きな問題です。

于 2013-01-04T13:04:30.273 に答える
0

あなたが説明した方法で (Andrey Nudko が 1 月 5 日の 13:22 に返信した方法ではなく) 本当に仕事をする必要がある場合は、他の視点からも問題を検討する必要があります。

いくつかのヒント:

  1. 環境全体 (JVM 以外) を確認してみてください。例えば:

  2. JVM内の「問題」

  3. スレッドの優先順位を変更してみてください: Java のスレッドに優先順位を設定する

于 2013-03-16T20:09:07.427 に答える
0

これが私の2セントです。Linux/Unix ベースのシステムで実行している場合、特定の CPU を特定のスレッド専用にする方法があります。本質的には、OS がどのようなスケジューリングでもその CPU を無視するようにすることができます。CPU の分離レベルを確認する

于 2015-11-12T23:56:11.220 に答える