7

多数のソケット接続を処理するプログラム(Webサービス、p2pシステムなど)で使用できるオプションがいくつかあるようです。

  1. ソケットごとにI/Oを処理するために、個別のスレッドを生成します。
  2. selectシステムコールを使用して、I/Oを単一のスレッドに多重化します。
  3. ポーリングシステムコールを使用して、I / Oを多重化します(選択を置き換えます)。
  4. epollシステムコールを使用して、ユーザー/システムの境界を介してソケットfdを繰り返し送信する必要がないようにします。
  5. ポーリングAPIを使用して、接続の総数の比較的小さなセットをそれぞれ多重化する多数のI/Oスレッドを生成します。
  6. epoll APIを使用して、独立したI / Oスレッドごとに個別のepollオブジェクトを作成することを除いて、#5と同じです。

マルチコアCPUでは、#5または#6が最高のパフォーマンスを発揮すると思いますが、これをバックアップするハードデータはありません。Webを検索すると、上記の#2、#3、および#4の作成者テストアプローチの経験を説明するこのページが表示されました。残念ながら、このWebページは約7年前のものであり、最近の明らかな更新は見つかりませんでした。

だから私の質問は、これらのアプローチのどれが人々が最も効率的であるとわかったか、そして/または上記のどのアプローチよりもうまく機能する別のアプローチがありますか?実際のグラフ、ホワイトペーパー、および/またはWebで利用可能な記事への参照をいただければ幸いです。

4

4 に答える 4

3

大規模な IRC サーバーを実行した私の経験によると、私たちは select() と poll() を使用していました (epoll()/kqueue() が利用できなかったため)。約 700 の同時クライアントで、サーバーは 100% の CPU を使用していました (irc サーバーはマルチスレッド化されていませんでした)。ただし、興味深いことに、サーバーは依然として良好に機能します。クライアント数が約 4,000 になると、サーバーの速度が低下し始めます。

その理由は、約 700 のクライアントで、select() に戻ると、処理に使用できるクライアントが 1 つになるためです。for() はスキャンをループして、どのクライアントが CPU のほとんどを消費するかを調べます。クライアントが増えるにつれて、select() を呼び出すたびに処理を必要とするクライアントが増えるため、より効率的になります。

epoll()/kqueue() に移行すると、同様の仕様のマシンで 10,000 クライアントを簡単に処理できるようになり、一部のマシン (確かにより強力なマシンですが、今日の基準では小さいと見なされるマシン) は、クライアントを 30,000 まで保持できました。汗。

私が SIGIO で見た実験では、レイテンシが非常に重要なアプリケーション、つまりアクティブなクライアントがほとんどなく、個々の作業をほとんど行わないアプリケーションでうまく機能することが示唆されているようです。

ほとんどの場合、select()/poll() よりも epoll()/kqueue() を使用することをお勧めします。クライアントをスレッド間で分割する実験は行っていません。正直なところ、スレッドを使った実験を正当化するために、フロント エンドのクライアント処理でさらに最適化作業を行う必要があるサービスを見つけたことがありません。

于 2008-12-30T11:32:17.530 に答える
2

私の経験から、あなたは#6で最高のパフォーマンスを得るでしょう。

また、libeventを調べて、これらの詳細の一部を抽象化することをお勧めします。少なくとも、あなたは彼らのベンチマークのいくつかを見ることができるでしょうベンチマーク結果

また、何個のソケットについて話しているのですか?少なくとも数百のソケットを取得し始めるまで、アプローチはおそらくそれほど重要ではありません。

于 2008-09-30T20:46:47.330 に答える
2

私はこの2年間、その特定の問題に取り組んできました(G-WAN Webサーバーの場合、これには多くのベンチマークとチャートが付属しており、これらすべてを公開しています)。

Linuxで最適に機能するモデルは、1つのイベントキュー(および、大量の処理の場合は複数のワーカースレッド)を備えたepollです。

処理が少ない(処理待ち時間が短い)場合は、複数のスレッドを使用すると1つのスレッドを使用する方が高速になります。

この理由は、epollがマルチコアCPUでスケーリングしないためです(同じユーザーモードアプリケーションで接続I / Oに複数の同時epollキューを使用すると、サーバーの速度が低下するだけです)。

私はカーネル内のepollのコードを真剣に調べていませんでしたが(これまではユーザーモードにのみ焦点を当てていました)、カーネル内のepoll実装はロックによって機能しなくなっていると思います。

これが、複数のスレッドを使用するとすぐに壁にぶつかる理由です。

言うまでもなく、Linuxが最高のパフォーマンスを発揮するカーネルの1つとしての地位を維持したいのであれば、このような状況の悪化は続くべきではありません。

于 2011-06-22T12:45:33.697 に答える
0

私は epoll() を広範囲に使用していますが、パフォーマンスは良好です。私は日常的に何千ものソケットをアクティブにして、最大 131,072 個のソケットでテストしています。そして epoll() はいつでもそれを処理できます。

複数のスレッドを使用し、それぞれがソケットのサブセットをポーリングします。これによりコードが複雑になりますが、マルチコア CPU を最大限に活用できます。

于 2008-09-29T16:44:35.937 に答える