2011-02-08 8 views
8

2〜3年前、人々が現代のスレッドライブラリが非常に良くなっていると主張している記事を読んで覚えています。リクエストごとのスレッドサーバーは、ノンブロッキングサーバーよりも簡単に書くことができるだけでなく、 、あまりにも。私はこれが、JavaスレッドをpthreadsにマッピングしたJVM(つまり、Javaのnioオーバーヘッドはコンテキスト切り替えオーバーヘッド以上のもの)でJavaでも実証されたと思います。リクエスト・モデルごとのスレッドは、ノンブロッキングI/Oより高速である可能性がありますか?

しかし、私はすべての「最先端の」サーバーが非同期ライブラリ(Java nio、epoll、さらにはnode.js)を使用していることがわかりました。これはasyncが勝ったことを意味しますか?

答えて

6

私の意見ではありません。両方のモデルがうまく実装されている場合(これは大きな要件です)、私はNIOのコンセプトが勝つはずだと思います。

コンピュータの中心にはコアがあります。あなたが何をしていても、コアを持つ以上にアプリケーションを並列化することはできません。つまり、4コアのマシンを使用している場合は、一度に4つの作業しかできません(ここではいくつかの詳細を説明していますが、これで十分です)。

コアではなくスレッド数が増えれば、あなたは無駄です。その廃棄物には2つの形があります。まず、余分なスレッド自体のオーバーヘッドです。次に、スレッド間の切り替えに費やされた時間です。どちらもおそらくマイナーですが、彼らはそこにいます。

理想的には、コアごとに1つのスレッドがあり、それらのスレッドのそれぞれがコアで100%の処理速度で実行されていることが理想的です。タスクの切り替えは理想的には起こりません。もちろん、OSはありますが、16コアマシンを使用してOS用に2〜3スレッドを残せば、残りの13〜14はあなたのアプリに向かって行きます。これらのスレッドは、入出力要件によってブロックされている場合のように、内で内のアプリケーションを切り替えることはできますが、OSレベルでそのコストを支払う必要はありません。あなたのアプリにすぐ書いてください。

このスケーリングの優れた例は、SEDA http://www.eecs.harvard.edu/~mdw/proj/seda/にあります。これは、標準的な要求ごとのスレッドモデルよりも負荷の方がはるかに優れたスケーリングを示しました。

私の個人的な経験はNettyです。私は単純なアプリを持っていた。 TomcatとNettyの両方でうまく実装しました。それから、100件の同時リクエスト(これは800以上と思われます)で負荷テストを行いました。やがてTomcatは動きが遅くなり、非常にバースト的な/遅れた動作を示しました。一方、Nettyの実装では応答時間が増加しましたが、全体的なスループットは非常に高かったです。

これは、堅実な実装に基づいています。 NIOはまだ時間の経過とともに良くなっています。私たちは、OSの機能をより有効に活用するために、JVMを実装する方法と同様に、よりうまく動作するようにサーバーOSを調整する方法を学習しています。勝者がまだ宣言されているとは思えませんが、NIOは最終的に勝者になると信じています。

+0

これは非常に興味深い現実世界のテストです。多くのアプリケーションでは、800件の同時リクエストがそれほど多くありません。私は、Tomcatの遅れがコンテキスト切り替え(またはGC、@可能性のある示唆)に起因しているかどうか疑問に思います。これは、要求ごとのスレッドモデル自体がTomcatの実装ではなくエラーであることを意味します。 – Graham

+1

公正であるために、これはクラスタではなく、テストされていた単一のサーバーでした。 800件のリクエスト私の経験では、同時に800件がかなり高いです。接続からの同時リクエストを区別することが重要です。その負荷で100msの範囲で応答時間が得られれば、毎秒8kの要求をサポートしています。それは単一の箱にとって悪くない。それを1日中スケーリングし、1台のサーバーで7億件のリクエストを処理します。それほど多くのアプリケーションにはそれほど必要なものはありませ – rfeak

6

十分なメモリがある限り、より高速です。

NIOは、接続が多すぎるとアイドル状態になるため、スレッドを保存してメモリを節約でき、スレッドごとのモデルよりも多くのユーザーを処理できます。

CPUはここでは直接的な要因ではありません。 NIOを使用すると、自分でスレッドモデルを実装する必要があります。これは、JVMのスレッドより速くなる可能性は低いです。

いずれの選択においても、メモリは究極のボトルネックです。負荷が増加し、使用メモリが最大に近づくと、GCは非常にビジーで、システムはしばしば100%CPUの症状を示します。

+0

これは意味があります。速いGoogleの検索では、64ビットマシン上のHotSpotのデフォルトスタックが1MBであることがわかりました(これはヒープではありませんが、ヒープのために残されているメモリの量が減ります)。これは、少なくともJavaの場合、スレッドごとのリクエストがC10Kには適していないことを意味します。しかし、メモリが制約条件であれば、何百もの同時接続に適している可能性があります。 – Graham

4

これまでに、私はrather interesting presentationが "なぜクライアントあたりの古いスレッドモデルが優れているのか"についていくつかの洞察を提供していました。測定値もあります。しかし、私はまだそれを考えています。私の意見では、ほとんどの(すべてではないにせよ)エンジニアリング上の意思決定がトレードオフであるため、この質問に対する最良の答えは「依存する」ことです。

+0

これは私が覚えているプレゼンテーションだったかもしれないと思います。 ErlangとScalaのアクターベースの並行性の新しい認識と組み合わせたこれらの観察(nioは遅い可能性があります)は私に、世界は同期モデルに向かっていると思いました。しかし、これらの言語の外では(そしてScalaが主に不正をしています)、@rfeakに遭遇したような実世界の問題にぶつかるまでは、同期としてデフォルトに固執すると思います。 – Graham

1

プレゼンテーションのように、スピードとスケーラビリティがあります。

クライアントが比較的少ない(たとえば< 100)ときに、リクエストごとのスレッドがほぼ確実に非同期ソリューションより速くなるシナリオがありますが、各クライアントの容量は非常に高いです。例えば100以上のクライアントがそれぞれ500のメッセージを送信/生成しているリアルタイムアプリです。リクエストごとのスレッドモデルは、非同期イベントループソリューションよりも効率的です。非同期は、多くのクライアント接続で待機しているサイクルを無駄にしないため、多くの要求/クライアントがある場合に優れていますが、待機時間の少ない大量のクライアントが少ない場合、効率が低下します。

NodeとNettyの著者は、これらのフレームワークが、少量の大量のクライアントでは高速ではなく、高いボリューム/多くの接続のスケーラビリティの状況に主に対応することを認識しています。

関連する問題