3

読み取り用の fd_set に接続ソケット記述子が含まれている単純な tcp サーバー アプリケーションを作成しました。サーバー アプリケーションは、メッセージを受信するたびに ACK を送信するだけです。クライアント アプリケーションは、サーバーから ACK を受信した後、次のメッセージのみを送信します。

// timeval == NULL
select(maxfd, &read_set, NULL, NULL, NULL)

これを行うと、パフォーマンスは約 3K メッセージ/秒になります。ack を送信してからクライアントからの応答を受信するまでのレイテンシは 0.3ms です。

// tm.tv_sec=0 and tm.tv_usec=0
select(maxfd, &read_set, NULL, NULL, tm)

しかし、これを行うと、パフォーマンスは 8,000 メッセージ/秒になり、レイテンシは 0.18 ミリ秒に低下します。

後者の場合、select は poll になります。後者のケースが最初のケースよりもはるかに優れている理由を誰か説明してもらえますか?

4

3 に答える 3

4

可能な答え

タイムアウトがゼロの場合、使用可能なデータがない場合、select() 呼び出しはすぐに戻ります。これにより、データが到着するまで積極的に CPU サイクルを消費して、ソケットのポーリングをビジー状態で待つことができます。

タイムアウトが NULL の場合、データがない場合、プロセスは WAIT_INTERRUPTIBLE 状態でスリープ状態になり、データが利用可能になるのを待ちます。これにより、少なくとも 2 つのコンテキスト スイッチのペナルティが発生します。1 つはプロセスから離れ、もう 1 つはデータが利用可能になったときにプロセスに戻ります。これの利点は、プロセスが CPU を放棄し、他のプロセスが実行できるようになることです。

スピンロックとセマフォを比較するようなものです。スピンロックは条件を待って CPU を「スピン」させますが、セマフォは CPU を解放します。スピンロックはパフォーマンスが向上しますが、CPU を占有するため、非常に短い待ち時間にのみ使用する必要があります。セマフォは他のプロセスとより協調的ですが、余分なコンテキスト スイッチが原因で顕著なオーバーヘッドが発生します。

于 2012-12-18T16:23:31.210 に答える
1

それはあなたの質問に答えませんが、あなたが本当に良いパフォーマンスを望んでいるなら、そして受信されたメッセージの割合がかなり高いなら、あなたはそれを試すことができます:

  • O_NONBLOCKで開く
  • 最初に読んでみてください
  • エラーコードEAGAINまたはEWOULDBLOCKで読み取りが失敗した場合は、timeval==NULLで選択を実行します
  • データを処理する
于 2012-12-18T16:42:46.377 に答える
-2

のマニュアルページはselect(2)言う

timeout は、select() が戻るまでの経過時間の上限です。timeval 構造体の両方のフィールドがゼロの場合、select() はすぐに戻ります。(これはポーリングに役立ちます。) timeout が NULL (タイムアウトなし) の場合、select() は無期限にブロックできます

追加された強調は私のものです。遅延が気になる場合は、 をご覧くださいepoll(4)

于 2012-12-18T16:19:50.087 に答える