web-dev-qa-db-ja.com

epollがselectより速いのはなぜですか?

私はselectがfdリストを調べなければならないという多くの比較を見てきましたが、これは遅いです。しかし、なぜこれを行う必要はありませんか?

51
amazingjxq

これについて多くの誤った情報がありますが、本当の理由はこれです:

典型的なサーバーは、たとえば200の接続を処理している場合があります。データの書き込みまたは読み取りが必要なすべての接続を処理し、さらに処理が必要になるまで待機する必要があります。待機中に、これらの200の接続のいずれかでデータを受信した場合、中断する必要があります。

selectを使用すると、カーネルはプロセスを接続ごとに1つずつ、200の待機リストに追加する必要があります。これを行うには、プロセスを待機リストにアタッチする「サンク」が必要です。プロセスが最終的に起動すると、200のすべての待機リストから削除する必要があり、それらのすべてのサンクを解放する必要があります。

対照的に、epollでは、epollソケット自体に待機リストがあります。プロセスは、1つのサンクのみを使用して、1つの待機リストにのみ配置する必要があります。プロセスが起動すると、1つの待機リストからのみ削除する必要があり、1つのサンクのみを解放する必要があります。

明確にするには、epollを使用して、epollソケット自体をこれらの200個の接続のそれぞれに接続する必要があります。しかし、これは、最初に受け入れられたときに、接続ごとに1回行われます。そして、これは、接続が削除されるたびに、接続ごとに1回破棄されます。対照的に、ブロックするselectを呼び出すたびに、監視対象のすべてのソケットのすべての待機キューにプロセスを追加する必要があります。

皮肉なことに、selectを使用すると、最大のコストは、アクティビティのないソケットにアクティビティがあったかどうかをチェックすることから生じます。 epollを使用すると、アクティビティがないソケットをチェックする必要はありません。アクティビティがあった場合、アクティビティが発生したときにepollソケットに通知していたからです。ある意味では、selectは、selectを呼び出すたびに各ソケットをポーリングしてアクティビティがあるかどうかを確認し、epollはそれをリグして、ソケットアクティビティ自体がプロセスに通知するようにします。

95
David Schwartz

epollselectの主な違いは、select()では、待機するファイル記述子のリストが単一のselect()の期間だけ存在することです。呼び出し、および呼び出しタスクは、単一の呼び出しの間、ソケットの待機キューにのみ留まります。一方、epollでは、待機する他の複数のファイル記述子からイベントを集約する単一のファイル記述子を作成します。そのため、監視対象のfdのリストは長続きし、タスクはソケットにとどまります。複数のシステムコールにわたる待機キュー。さらに、epoll fdは複数のタスク間で共有できるため、待機キュー上の単一のタスクではなく、epoll fd。 (実装の観点から、これは、関数ポインターとその関数に渡す_void*_データポインターを保持するソケットの待機キューによって抽象化されます)。

それで、メカニズムをもう少し説明するために:

  1. epollファイル記述子には、このfdにどのfdがアタッチされているかを追跡するプライベート_struct eventpoll_があります。 _struct eventpoll_には、このfdで現在_epoll_wait_ ingであるすべてのプロセスを追跡する待機キューもあります。 _struct epoll_には、現在読み取りまたは書き込みに使用できるすべてのファイル記述子のリストもあります。
  2. epoll_ctl()を使用してepoll fdにファイル記述子を追加すると、epollはそのfdの待機キューに_struct eventpoll_を追加します。また、fdが現在処理の準備ができているかどうかを確認し、準備ができている場合は、準備完了リストに追加します。
  3. _epoll_wait_を使用してepoll fdで待機すると、カーネルは最初に準備リストをチェックし、ファイル記述子が既に準備されている場合はすぐに戻ります。そうでない場合、それは_struct eventpoll_内の単一の待機キューに自分自身を追加し、スリープ状態に入ります。
  4. epoll() edされているソケットでイベントが発生すると、epollコールバックが呼び出されます。これにより、ファイル記述子がレディリストに追加され、現在待機中のウェイターも起動されますその_struct eventpoll_。

明らかに、_struct eventpoll_およびさまざまなリストと待機キューには多くの注意深いロックが必要ですが、それは実装の詳細です。

重要なことは、上記のどの時点でも、対象のすべてのファイル記述子をループするステップを説明しなかったことです。完全にイベントベースであり、fdの長続きするセットとレディリストを使用することにより、epollはO(n)の取得を回避できます操作の時間(nはファイル記述子の数)監視されています。

20
elite21