366

私はサーバーを作成しており、リクエストを受信すると、の各アクションを別々のスレッドに送信します。ほとんどすべてのリクエストがデータベースクエリを実行するため、これを行います。スレッドプールライブラリを使用して、スレッドの構築/破棄を削減しています。

私の質問は、このようなI / Oスレッドの適切なカットオフポイントは何ですか?大まかな見積もりだとは思いますが、何百人も話しているのでしょうか。数千?

このカットオフがどうなるかをどうやって理解するのでしょうか?


編集:

ご回答ありがとうございました。スレッド数の上限を確認するためにテストする必要があるようです。問題は、しかし、私がその上限に達したことをどうやって知ることができるかということです。正確に何を測定する必要がありますか?

4

12 に答える 12

252

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

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

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

実際には、コード自体で使用状況を監視し、次回の起動時に構成を調整することもできますが、それはおそらくやり過ぎです


明確化と精緻化のために:

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

私はスレッドとデータベースの接続プールコードを作成しましたが、それらには次の機能があります(パフォーマンスに不可欠であると私は信じています)。

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

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

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

(A)作業を行わないスレッドは、CPUの多くを使用しないため、通常はメモリ使用量(スタックなど)です。(B)スレッドが使用可能になるのを待つ必要があるため、リクエストが到着すると、通常、リクエストの処理が遅れます。

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

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

次に、必要なスレッドの数は、過去の使用状況によって異なります。実行する必要のある最小値は、これまでに実行した最小数+ A%であり、絶対最小値は(たとえば、Aのように構成可能にする)5です。

スレッドの最大数は、過去の最大値+ B%である必要があります。

また、動作の変化を監視する必要があります。何らかの理由で、使用量がかなりの時間使用可能の100%になる場合(クライアントのパフォーマンスに影響を与えるため)、再びB%高くなるまで、許可される最大値を増やす必要があります。


「正確に何を測定すればいいの?」に応えて 質問:

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

さらに、これはチューニングのために実稼働環境で実行する必要があります。事前に見積もりを取得することは問題ありませんが、どの本番環境がどのように機能するかはわかりません(そのため、これらすべてを実行時に構成する必要があります)。これは、着信するクライアント呼び出しが予期せず2倍になるなどの状況をキャッチするためです。

于 2009-01-27T00:51:10.783 に答える
43

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

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

これで、スタックサイズを調整してより多くのスレッドを組み込むことができますが、スレッド管理のオーバーヘッド(作成/破棄およびスケジューリング)を考慮する必要があります。特定のプロセスおよび特定のスレッドにCPUアフィニティを適用して、それらを特定のCPUに結び付け、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/

于 2010-11-18T20:06:04.790 に答える
19

スレッドが何らかの種類のリソース集約型の作業 (CPU/ディスク) を実行している場合、1 つまたは 2 つを超える利点はほとんど見られず、多すぎるとパフォーマンスがすぐに低下します。

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

適切な解決策は、リクエストをプールに配置し、スレッド プールからワーカー スレッドにディスパッチすることです (そして、継続的なスレッドの作成/破棄を回避することは、最初の優れたステップです)。

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

于 2009-01-27T01:03:53.097 に答える
9

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

もちろん、それは多くのことに依存するため、自分で測定する必要があります。

Combien de fils d'exécution ?で小節を完成させます (フランス語のみ) 。.

于 2009-01-27T08:42:24.997 に答える
6

私は多くの高度にマルチスレッド化されたアプリを作成しました。通常、潜在的なスレッドの数を構成ファイルで指定できるようにしています。特定の顧客向けに調整したとき、すべての CPU コアの使用率がかなり高くなるように数値を高く設定しましたが、メモリの問題が発生するほど高くはありませんでした (これらは当時の 32 ビット オペレーティング システムでした)。時間)。

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

これは、問題のシステムがアプリ専用であることを前提としており、他のアプリをうまくプレイする (飢えを避ける) 必要はないことに注意してください。

于 2011-06-08T18:12:39.880 に答える
4

「大きな鉄」の答えは、一般に、プロセッサ (CPU バウンド)、アーム (I/O バウンド) などの限られたリソースごとに 1 つのスレッドですが、リソースの正しいスレッドに作業をルーティングできる場合にのみ機能します。アクセスされます。

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

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

もちろん、これらすべてをスレッドの「重量」と比較検討する必要があります。残念ながら、ほとんどのシステムには非常に重いスレッド (そして、「軽量スレッド」と呼ばれるものは、まったくスレッドではないことが多い) を持っているため、ローサイドで過ちを犯した方がよいでしょう。

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

于 2012-01-15T15:13:15.893 に答える
3

考慮すべきことの 1 つは、コードを実行するマシン上に存在するコアの数です。これは、任意の時点で処理できるスレッド数のハード リミットを表します。ただし、あなたの場合のように、データベースがクエリを実行するのをスレッドが頻繁に待機することが予想される場合は、データベースが処理できる同時クエリの数に基づいてスレッドを調整することをお勧めします。

于 2009-01-27T00:51:42.730 に答える
3

これはあなたの質問を少し回避していると思いますが、それらをプロセスにフォークしてみませんか? ネットワーキングについての私の理解 (ぼんやりした昔から、私は実際にはネットワークをまったくコーディングしていません) は、各着信接続は個別のプロセスとして処理できるというものでした。プログラム全体を核攻撃します。

于 2009-01-27T00:55:16.547 に答える
2

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

于 2009-01-27T12:36:16.600 に答える
-6

ほとんどの場合、スレッド プールでこれを処理できるようにする必要があります。いくつかのコードを投稿するか、詳細を提供すると、スレッド プールのデフォルトの動作が最適ではない何らかの理由があるかどうかを簡単に確認できる場合があります。

これがどのように機能するかについての詳細は、http: //en.wikipedia.org/wiki/Thread_pool_patternを参照してください。

于 2009-01-27T00:53:37.797 に答える
-12

CPUコアと同じ数のスレッドが私がよく耳にするものです。

于 2009-01-27T00:48:45.437 に答える