12

非常に多くの(100K以上)長寿命の接続を維持する必要があるカスタムサーバーを実装しています。サーバーはソケット間でメッセージを渡すだけで、深刻なデータ処理は行いません。メッセージは小さいですが、それらの多くは毎秒送受信されます。レイテンシーの削減は目標の1つです。複数のコアを使用してもパフォーマンスが向上しないことを認識しているため、オブジェクトの呼び出しrun_oneまたはpollメソッドを使用して、サーバーを単一のスレッドで実行することにしました。io_serviceとにかく、マルチスレッドサーバーは実装がはるかに難しいでしょう。

考えられるボトルネックは何ですか?システムコール、帯域幅、完了キュー/イベントの逆多重化?ハンドラーのディスパッチにはロックが必要な場合があると思います(これはasioライブラリによって内部的に行われます)。boost.asioでキューロック(またはその他のロック)を無効にすることは可能ですか?

編集:関連する質問。syscallのパフォーマンスは複数のスレッドで向上しますか?私の感じでは、syscallはカーネルによってアトミック/同期されるため、スレッドを追加しても速度は向上しません。

4

2 に答える 2

17

数年前の私の質問を読みたいと思うかもしれませんが、 Blue Gene / Qスーパーコンピューター用のシステムソフトウェアを開発しているときに、Boost.Asioのスケーラビリティを最初に調査したときに質問しました。

100k以上の接続へのスケーリングは問題にはなりませんが、開いているファイル記述子の最大数など、明らかなリソースの制限に注意する必要があります。独創的なC10K論文をまだ読んでいない場合は、読むことをお勧めします。

単一のスレッドと単一のスレッドを使用してアプリケーションを実装した後io_service、を呼び出すスレッドのプールを調査し、特定のスレッドやCPUへのio_service::run()固定を調査することをお勧めします。io_serviceこれら3つの設計すべてのAsioドキュメントには複数の例が含まれており、SOに関するいくつかの質問と詳細情報があります。io_service::run()複数のスレッドを呼び出す場合はstrand、ハンドラーが共有データ構造に排他的にアクセスできるようにするためにを実装する必要がある場合があることに注意してください。

于 2013-02-26T17:52:13.283 に答える
10

boost :: asioを使用すると、ほぼ同じ開発コストでシングルスレッドまたはマルチスレッドサーバーを作成できます。シングルスレッドバージョンを最初のバージョンとして記述し、必要に応じてマルチスレッドに変換できます。

通常、boost :: asioのボトルネックは、epoll/kqueuereactorがミューテックスで動作していることだけです。したがって、1つのスレッドだけが同時にepollを実行しています。これにより、非常に小さなパケットを大量に処理するマルチスレッドサーバーがある場合にパフォーマンスが低下する可能性があります。しかし、とにかくそれは単なるシングルスレッドサーバーよりも高速であるはずです。

今あなたの仕事について。接続間でメッセージを渡すだけの場合は、マルチスレッドサーバーである必要があると思います。問題はシステムコール(recv / sendなど)です。命令はCPUに対して非常に簡単に実行できますが、システムコールはそれほど「軽い」操作ではありません(すべてが相対的ですが、タスク内の他のジョブに対して相対的です)。したがって、シングルスレッドでは、大きなsyscallのオーバーヘッドが発生します。そのため、マルチスレッドスキームを使用することをお勧めします。

また、io_serviceを分離して、「スレッドごとのio_service」イディオムとして機能させることもできます。これは最高のパフォーマンスを提供する必要があると思いますが、欠点があります。io_serviceの1つがキューを大きくしすぎると、他のスレッドはそれを助けないため、一部の接続が遅くなる可能性があります。一方、単一のio_serviceを使用すると、キューのオーバーランにより、ロックのオーバーヘッドが大きくなる可能性があります。できることはすべて-両方のバリアントを実行し、帯域幅/遅延を測定します。両方のバリアントを実装することはそれほど難しくないはずです。

于 2013-02-26T08:24:01.407 に答える