web-dev-qa-db-ja.com

スレッド数が多すぎますか。

私はサーバーを書いています、そして私はリクエストが入ってくるときにスレッドのそれぞれのアクションを分岐します。ほとんどすべてのリクエストがデータベースクエリを作成するためです。私はスレッドの構築/破壊を減らすためにスレッドプールライブラリを使っています。

私の質問はそうです - これらのようなI/Oスレッドのための良いカットオフポイントは何ですか?私はそれが単なる概算であることを知っています、しかし我々は何百もの話をしていますか?数千?


編集:

ご回答ありがとうございました。スレッドカウントの上限を確認するには、テストしなければならないようです。問題はそれだけではありません:私はどうやって私はその天井にぶつかったことを知っていますか?正確に何を測定すればいいですか?

277
ryeguy

2つのスレッドが多すぎると言う人もいるでしょう - 私はそのキャンプにはいません:-)

ここに私のアドバイスがあります:測定、推測しないでください。1つの提案は、それを設定可能にして最初は100に設定し、それからあなたのソフトウェアを公開して何が起こるかを監視することです。

スレッド使用量が3でピークに達すると、100は多すぎます。ほとんどの日で100のままの場合は、200まで増やして何が起こるのかを確認してください。

あなたは実際にあなた自身のコード自身に使用状況を監視させ、次回起動時に設定を調整させることができますが、おそらくやり過ぎです。


説明と説明のために:

私はあなた自身のスレッドプーリングサブシステムをローリングすることを提唱していません、どうしてもあなたが持っているものを使用してください。しかし、スレッドの適切なカットオフポイントについて質問していたので、スレッドプールの実装には作成されるスレッドの最大数を制限する機能があると思います(これは良いことです)。

私はスレッドとデータベースのコネクションプーリングコードを書きました、そしてそれらは以下の機能を持っています(私はパフォーマンスのために不可欠であると信じます):

  • アクティブスレッドの最小数.
  • 最大スレッド数.
  • しばらく使用されていないスレッドをシャットダウンします。

1つ目は、スレッドプールクライアントに関して最小パフォーマンスのベースラインを設定します(このスレッド数は常に使用可能です)。 2番目は、アクティブスレッドによるリソース使用量の制限を設定します。 3つ目は、リソース使用量を最小限に抑えるために、静かな時間にベースラインに戻ります。

未使用のスレッドを持つことによるリソース使用量(A)と、作業を実行するのに十分なスレッドを持たないことによるリソース使用量(B)とのバランスをとる必要があります。

(A)は一般にメモリ使用量(スタックなど)です。何もしていないスレッドはCPUをあまり使用しないからです。スレッドが使用可能になるのを待つ必要があるため、(B)は一般に、要求が到着したときの要求の処理における遅延です。

それがあなたが測定する理由です。あなたが言うように、あなたのスレッドの大多数はデータベースからの応答を待っているので、それらは実行されません。許容スレッド数に影響する2つの要因があります。

最初のものは利用可能なDB接続の数です。 DBMSで増やすことができない限り、これは厳しい制限になる可能性があります。この場合、DBMSが無制限の数の接続を確立できると想定します(ただし、これも理想的に測定する必要があります)。

そして、あなたが持っているべきスレッドの数はあなたの過去の使用に依存します。実行する必要がある最小値は、これまでに実行したことのある最小数+ A%で、絶対最小値は(たとえば、Aのように構成可能にする)5です。

最大スレッド数は、過去の最大数+ B%です。

また、行動の変化を監視する必要があります。何らかの理由で、使用率がかなりの時間にわたって使用可能容量の100%に達すると(それがクライアントのパフォーマンスに影響を与えるため)、再び最大B%になるまで許容最大値を上げる必要があります。


「何を測ればいいの?」に答えて質問:

具体的に測定する必要があるのは、負荷がかかっている状態での同時使用(DB呼び出しからの戻りを待つなど)の最大スレッド数です。次に、exampleに対して10%の安全率を追加します(他のポスターでは、私の例を固定推奨事項と見なしているため、強調しています)。

さらに、これはチューニングのために運用環境で行う必要があります。事前に見積もりを取得しても構いませんが、どのプロダクションで問題が発生するのかわかりません(これが、実行時にこれらすべてを設定可能にする必要がある理由です)。これは、着信したクライアントコールが予想外に2倍になるなどの状況を捉えるためです。

181
paxdiablo

この質問はかなり徹底的に議論されました、そして私はすべての応答を読む機会を得ませんでした。しかし、ここでは、特定のシステム内で平和的に共存できる同時スレッド数の上限を見ながら考慮すべき点がいくつかあります。

  1. スレッドスタックサイズ:Linuxでは、デフォルトのスレッドスタックサイズは8MBです(それを見つけるにはulimit -aを使用できます)。
  2. 特定のOSバリアントがサポートする最大仮想メモリ。 Linux Kernel 2.4は2 GBのメモリアドレス空間をサポートします。カーネル2.6では、私はもう少し大きい(3GB)
  3. [1]は与えられたMax VM Supportedあたりの最大スレッド数の計算を示しています。 2.4の場合、スレッド数は約255です。 2.6の場合、数値は少し大きくなります。
  4. どのようなカーネルスケジューラがありますか。 Linux 2.4カーネルスケジューラを2.6と比較すると、後者はO(1)スケジューリングをシステムに存在するタスクの数に依存せずに提供しますが、最初のものはよりO(n)です。そのため、カーネルスケジュールのSMP機能も、システム内の持続可能なスレッドの最大数に役立ちます。

これで、スタックサイズを調整してより多くのスレッドを組み込むことができますが、その場合はスレッド管理のオーバーヘッド(作成/破棄およびスケジューリング)を考慮する必要があります。 CPU間のスレッドマイグレーションのオーバーヘッドを回避し、コールドキャッシュの問題を回避するために、特定のプロセスだけでなく特定のスレッドに対してもCPU Affinityを適用して特定のCPUに結び付けることができます。

自分の望むところで何千ものスレッドを作成することができることに注意してください、しかしLinuxがVMを使い果たしたとき、それはただランダムにプロセス(したがってスレッド)を強制終了し始めます。これは、ユーティリティプロファイルが制限されないようにするためです。 (効用関数は与えられた量のリソースに対するシステム全体の効用について知らせる。この場合CPUサイクルとメモリの一定のリソースで、効用曲線はますます多くのタスクで平らになる)。

私はWindowsカーネルスケジューラもリソースの過剰利用に対処するためにこの種のことをすると確信しています

[1] http://adywicaksono.wordpress.com/2007/07/10/i-can-not-create-more-than-255-threads-on-linux-what-is-the-solutions /

34
Jay D

スレッドが何らかのリソースを大量に消費する作業(CPU /ディスク)を実行している場合、1〜2を超える利点が見られることはめったになく、多すぎるとパフォーマンスが急激に低下します。

「ベストケース」とは、最初のスレッドが完了している間、後のスレッドが停止したり、競合の少ないリソースでオーバーヘッドの低いブロックが発生したりすることです。最悪の場合、あなたはキャッシュ/ディスク/ネットワークをスラッシングし始め、全体的なスループットが低下します。

良い解決策は、プール内のワーカースレッドにディスパッチされるリクエストをプールに配置することです(そして、そうです、継続的なスレッドの作成/破壊を避けることは素晴らしい第一歩です)。

このプール内のアクティブなスレッドの数は、プロファイリングの結果、実行しているハードウェア、およびマシンで発生している可能性があるその他の事項に基づいて、調整および調整できます。

16
Andrew Grant

あなたが心に留めておくべきことの一つは、python(少なくともCベースのバージョン)がマルチコアマシンのパフォーマンスに大きな影響を与える可能性がある グローバルインタプリタロック と呼ばれるものを使用していることです。

あなたが本当にマルチスレッドのpythonを最大限に必要とするなら、あなたはJythonか何かを使うことを考慮したいかもしれません。

9
Chad Okere

Paxが正しく言ったように、測定して、推測しないでくださいDNSwitness のために私がしたことと結果は驚くべきものでした。理想的なスレッド数は思ったよりはるかに多く、最速の結果を得るためには15,000スレッドのようなものでした。

もちろん、それは多くのことに依存します、それであなたはあなた自身を測定しなければなりません。

Combien de filsd'exécution? に完全な対策(フランス語のみ)。

7
bortzmeyer

私はたくさんの重いマルチスレッドのアプリを書いた。私は一般的に潜在的なスレッドの数を設定ファイルで指定することを許可します。特定の顧客向けにチューニングしたとき、私はすべてのCPUコアの使用率がかなり高くなるのに十分高い数を設定しましたが、メモリの問題に遭遇するほど高くはありませんでした(これらは32ビットオペレーティングシステムでした)。時間)。

別の言い方をすれば、CPU、データベースのスループット、ディスクのスループットなど、ボトルネックになったら、スレッドを追加しても全体的なパフォーマンスは向上しません。しかし、その点に到達するまで、さらにスレッドを追加してください。

これは問題となっているシステムがあなたのアプリケーション専用であることを前提としています、そしてあなたは他のアプリケーションをうまくプレイする必要はありません(飢えを避ける)。

4
Matthew Lund

「ビッグアイアン」の答えは、通常、限られたリソースごとに1つのスレッド(プロセッサ(CPUバウンド)、アーム(I/Oバウンド)など)です。アクセスする。

それが不可能な場合は、代替可能なリソース(CPU)と代替不可能なリソース(武器)があると考えてください。 CPUの場合、各スレッドを特定のCPUに割り当てることは重要ではありませんが(キャッシュ管理に役立ちますが)、武器の場合、スレッドを武器に割り当てることができない場合、待ち行列理論と武器を維持するのに最適な数になります。忙しい。一般的に、使用しているアームに基づいてリクエストをルーティングできないのであれば、アームあたり2〜3のスレッドを使用するのが正しいと考えています。

スレッドに渡された作業単位が合理的にアトミックな作業単位を実行しない場合、問題が生じます。たとえば、ある時点でスレッドがディスクにアクセスし、別の時点でネットワーク上で待機しているとします。これにより、追加のスレッドが入り込んで有用な作業を行う可能性がある「クラック」の数が増えますが、追加のスレッドが互いのキャッシュなどを汚染してシステムを使い果たす機会も増えます。

もちろん、あなたは糸の「重さ」に対してこれらすべてを秤量しなければなりません。残念なことに、ほとんどのシステムは非常にヘビー級のスレッドを持っています(そしてそれらが「ライトウェイトスレッド」と呼ぶものはまったくスレッドではありません)。

私が実際に見たことは、非常にわずかな違いが、最適なスレッド数に大きな違いを生む可能性があるということです。特に、キャッシュの問題とロックの競合は、実際の同時実行量を大幅に制限する可能性があります。

3
Hot Licks

考慮すべき点の1つは、コードを実行するマシン上にコアがいくつ存在するかです。これは、同時に実行できるスレッド数に対する厳しい制限を表しています。しかし、あなたの場合のように、データベースがクエリを実行するのをスレッドが頻繁に待っていると予想される場合、データベースが同時に処理できるクエリの数に基づいてスレッドを調整したいと思うでしょう。

2
newdayrising

私はこれがあなたの質問には少し避けていると思いますが、なぜそれらをプロセスに分岐させないのですか?ネットワーキングについての私の理解は(昔の霞んだ日から、私はネットワークをまったくコーディングしていません)、それぞれの入ってくる接続を別々のプロセスとして扱うことができるということでした。プログラム全体を無効にします。

2
mmr

ryeguy、私は現在、同様のアプリケーションを開発していて、私のスレッド数は15に設定されています。残念ながら、20に増やすとクラッシュします。そのため、これに対処する最善の方法は、現在の設定でXの数より多くても少なくても許容されるスレッドであるかどうかを測定することです。

1
hyperboreean