2016-07-07 20 views
10

私の問題:スレッドがTIMED_WAIT状態(寝ていない)のとき待機中のスレッドのリソース消費

は、JVM内のスレッドの多くは、リソース(メモリ、CPU)を大量に消費するん>時間の99.9% ?スレッドが待機しているときに、必要なものがあれば、どれくらいのCP​​Uオーバーヘッドを維持するのにかかるコストがかかりますか?

答えはJVM以外の環境(Linuxカーネルなど)にも当てはまりますか?

コンテキスト:

私のプログラムは、スペースを消費する多数のパッケージを受け取ります。これは、異なるパッケージ内の類似の属性の数を格納します。パッケージを受け取ってから一定時間後(数時間または数日かかる可能性があります)、その特定のパッケージは期限切れとなり、パッケージの提供数は減るべきです。

現在、私はすべてのパッケージをメモリまたはディスクに保存することでこれらの機能を実現しています。 5分ごとに、期限切れのパッケージをストレージから削除し、残りのパッケージをスキャンして属性を数えます。この方法では大量のメモリが使用され、時間の複雑さが犠牲になります(時間とメモリにはO(n)、nは有効期限が切れていないパッケージの数です)。これにより、プログラムのスケーラビリティがひどくなります。

この問題にアプローチする別の方法の1つは、パッケージが到着するたびに属性カウントをインクリメントし、パッケージの有効期限が切れた後に属性数を減らすスレッドを開始することです(Timer())。これにより、嵩張ったパッケージをすべて保管し、時間の複雑さをO(1)に削減する必要がなくなります。しかし、私のプログラムではスレッド数がO(n)になり、パフォーマンスが低下する可能性があるため、別の問題が発生します。ほとんどのスレッドはTIMED_WAIT状態(JavaのTimer()Object.wait(long)メソッドを呼び出します)のライフサイクルの大部分を占めているため、CPUに非常に大きな影響を与えますか?

+0

考えているスレッドはいくつありますか?何百もの人が、スレッドのチェックやスケジューリングが必要なときにカーネルに課金するのではないかもしれませんが、もし500+をキューに入れているなら、あなたのアプローチを再検討したいかもしれません。 – txtechhelp

+0

私はおそらく数百人以上あります。カーネルが 'TIMED_WAIT'のスレッドを常にチェックしなければならない理由を説明してください。私は、カーネルがこれを具体的にどのようにしているかについての情報を見つけようとしましたが、望ましい情報は見つかりませんでした。 – PhotometricStereo

+1

ScheduledExecutor /単一スレッドでの有効期限のタイムスタンプ別の優先度キュー。 – zapl

答えて

9

まず、Java(または.NET)スレッド!=カーネル/ OSスレッド。

Java Threadは、システムスレッドの機能の一部を抽象化する高レベルのラッパーです。これらの種類のスレッドは管理対象スレッドとも呼ばれます。カーネルレベルでは、スレッドは実行中で実行中ではない2つの状態しか持たない。カーネルが追跡しているいくつかの管理情報(スタック、命令ポインタ、スレッドIDなど)がありますが、TIMED_WAITING状態(.NETはWaitSleepJoinに相当)のスレッドとしてカーネルレベルに存在しません状態)。これらの「状態」は、そのようなコンテキスト内にのみ存在します(なぜ、C++ std::threadにはstateメンバーがないのですか)。管理されたスレッドがブロックされている場合、管理されたレベルでブロックされる方法に応じて、いくつかの方法でそのように処理されています。私がOpenJDKでスレッドコードを見てきた実装では、マネージド・ウェイトを処理するためのセマフォを利用しています(これは.NETコアだけでなく、「マネージ」スレッド・クラスのようなC++フレームワークでも見られます)ライブラリ)を使用し、他のタイプの待機/ロックにmutexを使用します。

ほとんどの実装では、ある種のロック機構(セマフォやミューテックスのような)を利用するため、カーネルは一般的に同じことをします(少なくともあなたの質問がある限り)。つまり、カーネルは「実行」キューからスレッドを取り出し、それを「待機」キュー(context switch)に入れます。スレッドのスケジューリング、具体的にはカーネルがスレッドの実行をどのように処理するかは、このQ & Aの範囲を超えています。特に、Javaに関しては問題があります.Javaは非常に異なる種類のOSで実行できます各スレッドは完全に異なるスレッドを処理します)。スレッドがTIMED_WAIT状態(寝ていない)のとき

は、JVM内のスレッドの多くは、リソース(メモリ、CPU)を大量に消費するん>時間の99.9%を:より直接ご質問に答える

これには、作成されたスレッドがJVM(スタック、ID、ガベージコレクタなど)用のメモリを消費し、カーネルがカーネルのスレッドを管理するためにカーネルメモリを消費するレベル。あなたが特にそう言わない限り、消費されるメモリは変化しません。スレッドがスリープしているか実行中の場合、メモリは同じです。

CPUは、スレッドのアクティビティと要求されたスレッドの数に基づいて変更されるものです(スレッドはカーネルリソースを消費するため、カーネルレベルで管理する必要があります。それらを管理するためには、より多くのカーネル時間を消費しなければならない)。

は(それがデザインのポイントの一部です)のスレッドをスケジュールして実行するカーネル時間が極めて微細であることを覚えておいてください、それはまだあなたがスレッドのたくさんを実行する予定がある場合を検討するものです。さらに、アプリケーションがCPU(またはクラスタ)上で数個のコアで実行されていることが分かっている場合は、利用可能なコアの数が少ないほど、カーネルがコンテキストを切り替える必要があります。

スレッドが待機しているときに、必要な場合にスレッドを維持するために必要なCPUオーバーヘッドはいくらですか?

なし。上記を参照してください。スレッドの管理に使用されるCPUオーバーヘッドは、スレッドコンテキストに基づいて変更されません。余分なCPUがコンテキスト切り替えに使用される可能性がありますが、余分なCPUはアクティブ時にスレッド自体によって利用されますが、CPUには追加の「コスト」はありません。待機スレッド対実行スレッド。

回答はLinuxカーネルのような非JVM関連の環境にも当てはまりますか?

はい、いいえ。前述したように、管理されたコンテキストは、一般に、これらのタイプの環境(Java、.NET、PHP、Luaなど)の大部分に適用されますが、これらのコンテキストはさまざまで、スレッドのイディオムや一般的な機能は使用されるカーネルによって異なります。したがって、ある特定のカーネルがプロセスごとに1000以上のスレッドを処理することができる一方で、ハード制限があるものもあれば、プロセスあたりのスレッド数が多い他の問題があるものもあります。どのような限界があるのか​​を知るためにOS/CPUの仕様を参照する必要があります。

スレッドのほとんどがTIMED_WAIT状態になりますので

、それはまだ非常に大規模な方法でCPUに影響を与えない彼らのライフサイクルの大半、(Javaのタイマーは、()はObject.wait(long)メソッドを呼び出します) ?

いいえ(ブロックされたスレッドの部分)ですが、考慮すべき点:これらのスレッドのすべて(または> 50%)がまったく同じタイミングで実行する必要がある場合あなたのパッケージを管理しているスレッドがほんの少ししかない場合、それは問題ではないかもしれませんが、あなたは500+を持っていると言います。同時に250スレッドすべてが目覚めてしまうと、大量のCPU競合が発生します。

コードを投稿していないので、シナリオに特定の提案をするのは難しいですが、属性の構造をクラスとして保存し、そのクラスをリストまたはハッシュマップに保存する傾向がありますTimer(または別のスレッド)で参照されて、現在の時刻がパッケージの満了時刻と一致するかどうかを調べると、「期限切れ」コードが実行されます。これにより、スレッド数が1に、アクセス時間がO(1)に削減されます。コードなしでは、あなたのシナリオではその提案はうまくいかないかもしれません。

希望に役立ちます。

+0

素敵な説明。 – hakunami

関連する問題