2013-02-25 13 views
7

同じプログラムをスレッドとして複数回実行しているシングルコアマシンで、新しいスレッドの作成をいつ停止するかを決める最良の方法は何ですか?CPU上で実行されるスレッドの最大数を最適化する

スレッドはWebコンテンツを取得して処理しています。つまり、スレッドが終了するまで、各スレッドの負荷は常に一定ではありません。

CPU/RAMの負荷を監視し、負荷が一定のしきい値に達するとスレッドの作成を停止するスレッドがあると思っていますが、特定のスレッド数に達した場合はスレッドの作成を停止し、 CPUが過負荷になることはありません。

これを達成するためにどのような技術がありますか?

多くのおかげで、 ウラジミール

+3

あなたは正しい道にいると思います。考慮すべきことの1つは、常にIOを待つのではなく、スレッドが常にビジーであるように、NIOとセレクタを使用することです。そうでなければピークと谷を持たずにスループットを最大化するのは難しいでしょう。 – Gray

+0

グレイはそれに私を打つ:) IOをブロックするとRAMを無駄にし、ほとんど何も待っているスレッドのばかげた大量が必要になります。 –

+0

自分でスレッドを作成したくないかもしれません。 'Runnable'や' Callable'タスクのためにスレッドを再利用する 'ExecutorService'を使い、破壊スレッドを作成するオーバーヘッドを減らします。 –

答えて

1

現在のプロセスによって使用されるCPUを監視することにより、これを行うことは困難になるだろう。それらの数字は現実的に遅れがちで、その結果はピークと谷となるでしょう。問題はスレッドがIOによってブロックされることがほとんどで、近い将来にバイトが読み込めるかどうかを予測する良い方法がないことです。

これは、特定の最大スレッド数(1つのプロセッサでは4とします)でThreadPoolExecutorで開始してから、10秒間ごとに負荷平均を確認することができます。負荷平均値があなたの望む値よりも低い場合は、setMaximumPoolSize(...)と大きな値を指定して次の10秒間増やすことができます。アプリケーションのパフォーマンスを円滑にするために、各計算の間に30秒以上ポーリングする必要があります。

次のコードを使用して、すべてのスレッドの合計CPU時間を追跡できます。それは、代わりにあなたのクモのためのCPUのレベルを最大化しようとしているのはそれに

long total = 0; 
    for (long id : threadMxBean.getAllThreadIds()) { 
     long cpuTime = threadMxBean.getThreadCpuTime(id); 
     if (cpuTime > 0) { 
      total += cpuTime; 
     } 
    } 
    // since is in nano-seconds 
    long currentCpuMillis = total/1000000; 

を行うための最善の方法だかどうかわからない、あなたは、スループットを最大化しようと考えるかもしれません。単位時間あたりのspideredページ数のサンプルを取り、最大化するまでExecutorServiceの最大スレッド数を増減します。

考慮すべき点の1つは、常にIOを待つのではなく、スレッドが常にビジーであるように、NIOとセレクタを使用することです。ここにはgood example tutorial about NIO/Selectorsがあります。 Pyronetを使用することも考えられますが、これはNIOの優れた機能を提供するようです。

+0

私は「Pyronet」をクリックして約150のダウンロードをしています。誰かが、プロジェクトの一部としてユーザーベースの小さなライブラリを含むのはなぜですか? – Cratylus

+0

これに代わるものがなく、ホイール@Cratylusを再発明したくない場合。 :-) – Gray

1

async I/Oが適切でない場合は、スレッドプールを使用することを検討します。 ThreadPoolExecutorなので、スレッドの作成、破棄、再作成のオーバーヘッドはありません。

次に、最高のパフォーマンスを提供するスレッドの最大数を調整するパフォーマンステストを行います。

パフォーマンステストを20スレッドで実行して最適な値にするまで、10スレッドから開始できます。同時に、私はあなたのOSに依存するシステムツールを使って、スレッド実行キュー、JVMなどを監視します。

パフォーマンステストでは、テストが繰り返し可能であることを確認する必要があります(つまり、 )とあなたのプログラムが使用する実際の入力を表す。