とスレッドプールの違いを誰か説明できepoll
ますか?poll
- 長所/短所は何ですか?
- フレームワークに関する提案はありますか?
- 簡単な/基本的なチュートリアルの提案はありますか?
- とは Linux 固有
epoll
のpoll
ようです... Windows 用の同等の代替手段はありますか?
とスレッドプールの違いを誰か説明できepoll
ますか?poll
epoll
のpoll
ようです... Windows 用の同等の代替手段はありますか?Threadpool は実際には poll や epoll と同じカテゴリには当てはまらないため、「接続ごとに 1 つのスレッドで多くの接続を処理するためのスレッドプール」のようにスレッドプールを参照していると仮定します。
epoll
が、明らかな方法 (すべてのスレッドが をブロックするepoll_wait
) は役に立ちません。なぜなら、epoll はそれを待機しているすべてのスレッドを起動するため、それでも同じ問題が発生するからです。
futex
たとえば、スレッドごとの早送りキューと組み合わせて、ここであなたの友達です。ドキュメントが不十分で扱いにくいですが、futex
必要なものを正確に提供します。epoll
一度に複数のイベントを返す可能性がfutex
あり、効率的かつ正確に制御された方法で、一度にN 個のブロックされたスレッドをウェイクアップできます (N がmin(num_cpu, num_events)
理想的です)。fork
(別名オールドファッションスレッドプール)
fork
でも「無料」ではありませんが、オーバーヘッドはほとんどコピーオンライトメカニズムによって統合されています。変更も加えられた大規模なデータセットでは、かなりの数のページ フォールトfork
が発生し、パフォーマンスに悪影響を及ぼす可能性があります。poll
/select
epoll
epoll_ctl
)
。epoll_wait
( )
poll
仕組みの反対の方法timerfd
and で非常にうまく機能しますeventfd
(驚くべきタイマーの解像度と精度も)。signalfd
、ぎこちないシグナル処理をなくし、非常に洗練された方法でシグナルを通常の制御フローの一部にします。eventfd
が、(現在まで) 文書化されていない機能が必要です。poll
ある可能性があり、同等またはそれ以上のパフォーマンスを発揮する可能性があります。epoll
「魔法」を行うことはできません。つまり、発生するイベントの数に関しては、依然として必然的に O(N)です。epoll
、新しい syscall とうまく連携します (最大で指定した数まで、利用可能な数だけ)。これにより、ビジー状態のサーバーで 1 回の syscall でたとえば 15 個の EPOLLIN 通知を受信し、2 回目の syscall で対応する 15 個のメッセージを読み取ることができます (syscall の 93% の削減!)。残念なことに、1 回の呼び出しですべての操作が同じソケットを参照するため、UDP ベースのサービスで最も役に立ちます (TCP の場合、アイテムごとにソケット記述子を受け取る一種の syscall が必要です!)。recvmmsg
maxevents
recvmmsg
recvmmsmsg
EAGAIN
あり、使用する場合でも確認する必要があります。これは、レポートの準備が整っていて、その後の読み取り (または書き込み)がまだブロックされるというepoll
例外的な状況があるためです。これは、一部のカーネルの/にも当てはまります (ただし、おそらく修正されています)。epoll
poll
select
EAGAIN
、低速の送信者を完全に枯渇させながら、高速の送信者からの新しい受信データを無期限に読み取ることができます (データが十分に速く受信し続ける限り、EAGAIN
かなりの時間表示されない可能性があります! )。poll
/にも同様に適用されselect
ます。epoll_wait
さらに、前回の呼び出し以降 (または前回の呼び出しがなかった場合は記述子が開かれた以降) に IO アクティビティが発生したかどうかを通知することを示しています。epoll_wait
、誰かが最後にまたは epoll_wait
記述子の読み取り/書き込み関数、その後は、誰かが記述子の読み取り (または書き込み) 関数を呼び出した後に発生する操作について、次のスレッドを呼び出しているか、既にブロックされているスレッドに 再び準備ができていることを報告するだけです。 、あまりにも...ドキュメントが示唆しているものとはまったく異なります。epoll_wait
kqueue
epoll
性、異なる使用法、同様の効果。libevent -- 2.0 バージョンは、Windows での完了ポートもサポートしています。
ASIO -- プロジェクトで Boost を使用している場合は、もう探す必要はありません。これはすでに boost-asio として利用できます。
上記のフレームワークには、詳細なドキュメントが付属しています。Linux のドキュメントと MSDN では、epoll と補完ポートについて詳しく説明しています。
epoll を使用するためのミニチュートリアル:
int my_epoll = epoll_create(0); // argument is ignored nowadays
epoll_event e;
e.fd = some_socket_fd; // this can in fact be anything you like
epoll_ctl(my_epoll, EPOLL_CTL_ADD, some_socket_fd, &e);
...
epoll_event evt[10]; // or whatever number
for(...)
if((num = epoll_wait(my_epoll, evt, 10, -1)) > 0)
do_something();
IO 完了ポートのミニチュートリアル (異なるパラメーターで CreateIoCompletionPort を 2 回呼び出すことに注意してください):
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0); // equals epoll_create
CreateIoCompletionPort(mySocketHandle, iocp, 0, 0); // equals epoll_ctl(EPOLL_CTL_ADD)
OVERLAPPED o;
for(...)
if(GetQueuedCompletionStatus(iocp, &number_bytes, &key, &o, INFINITE)) // equals epoll_wait()
do_something();
(これらのミニチュートリアルでは、あらゆる種類のエラー チェックが省略されています。タイプミスがないことを願っていますが、ほとんどの場合、いくつかのアイデアを得るには問題ありません。)
編集:
完了ポート (Windows) は、概念的には epoll (または kqueue) とは逆に機能することに注意してください。それらは、その名前が示すように、準備完了ではなく、完了を示します。つまり、非同期リクエストを開始し、しばらくして完了したことを知らされるまでそれを忘れます (成功したか、それほど成功しなかったかのどちらかであり、「すぐに完了した」という例外的なケースもあります)。
epoll を使用すると、「一部のデータ」 (場合によっては 1 バイト程度) が到着して使用可能になるか、ブロックせずに書き込み操作を実行できる十分なバッファー スペースがあることが通知されるまでブロックします。そうして初めて、実際の操作を開始し、ブロックされないことが期待されます (予想される以外は、厳密な保証はありません。したがって、記述子を非ブロックに設定し、EAGAIN [EAGAINおよびEWOULDBLOCK ] を確認することをお勧めします。ソケットの場合、うれしいことに、標準では 2 つの異なるエラー値が許容されます])。