1. ホーム
  2. networking

[解決済み] Twistedのselect/pollリアクターとepollリアクターの注意点

2023-01-07 01:53:41

質問

私が読み、経験したすべて (Tornado ベースのアプリケーション) は、ePoll が Select および Poll ベースのネットワーキング、特に Twisted の自然な代替品であると信じるに至ります。 より良い技術や方法論が代償を伴わないというのはかなり稀です。

epoll と代替品の数十の比較を読むと、epoll は明らかに速度とスケーラビリティのチャンピオンであり、特に、それは素晴らしい直線的な方法でスケールすることがわかります。 とはいえ、プロセッサとメモリの使用率についてはどうでしょうか?

解決方法は?

非常に少数のソケット (もちろんハードウェアによって異なりますが、10 以下のオーダーのものについて話しています) では、メモリ使用量と実行速度で epoll に勝る select が使用できます。 もちろん、そのような少数のソケットでは、両方のメカニズムが非常に高速であるため、ほとんどの場合、この差はあまり気になりません。

しかし、1 つの明確化です。 select と epoll の両方が線形にスケールします。 しかし、大きな違いは、ユーザースペースに面した API が異なるものに基づく複雑さを持つことです。 のコストは select の呼び出しのコストは、渡したファイル記述子のうち最も大きな番号の値でおおよそ決まります。 単一の fd で 100 を選択する場合、単一の fd で 50 を選択する場合の約 2 倍のコストになります。 最高値より低い fd を追加することは無料ではないので、実際にはこれより少し複雑になりますが、これはほとんどの実装の良い第一近似値です。

epoll のコストは、実際にイベントが発生しているファイル記述子の数に近くなります。 200 個のファイル記述子を監視しているが、そのうち 100 個にしかイベントがない場合、(非常に大まかには)それらの 100 個のアクティブなファイル記述子に対してのみ料金を支払っていることになります。 ここが、selectと比較してepollの大きな利点の一つです。 もし、ほとんどアイドル状態のクライアントが1000個あったとしても、selectを使えば、1000個すべてに対してお金を払うことになります。 しかし、epoll を使用すると、数台しか持っていないのと同じように、いつでもアクティブなものに対してのみお金を払うことになります。

これらのことはすべて、epoll がほとんどのワークロードでより少ない CPU 使用量につながることを意味します。 メモリ使用量に関しては、ちょっとした投げやりな感じです。 select は、非常にコンパクトな方法(ファイル記述子あたり1ビット)で必要なすべての情報を表現することに成功しています。 また、FD_SETSIZE(通常は 1024)の制限によって select で使用できる 3 つの fd セットそれぞれに対して 128 バイト以上を費やすことはないということです。 select で使用できる 3 つの fd セット (読み取り、書き込み、例外) それぞれについて 128 バイト以上を費やすことはないということです。 これらの最大 384 バイトと比較すると、epoll は一種の豚です。 各ファイル記述子はマルチバイトの構造体で表現されます。 しかし、絶対的に見れば、それでも大したメモリ消費量にはならないでしょう。 数十キロバイトで膨大な数のファイルディスクリプタを表現できるのです(1000ファイルディスクリプタあたり大体20kくらいかな)。 そして、その384バイトをすべて select を使用すると、その値は 1024 になりますが、epoll を使用すると 20 バイトしか使用しません。 それでも、これらのすべての数はかなり小さいので、大きな違いはありません。

そして、おそらくすでにご存知のように、FD_SETSIZE ファイル記述子に制限されないという epoll の他の利点もあります。 FD_SETSIZE ファイル記述子に限定されないということです。 そして、ファイルディスクリプタがひとつだけで、その値が FD_SETSIZE よりも大きい場合、epoll はそのファイルディスクリプタでも動作します。 select は動作しません。

ランダムに、私はまた、最近、1つのわずかな欠点を発見しました。 epoll と比較して select または poll . これらの3つのAPIはいずれも通常のファイル(つまりファイルシステム上のファイル)をサポートしていませんが selectpoll は、このような記述子を常に読み取り可能、かつ、常に書き込み可能であると報告することで、このサポートの欠如を提示しています。 このため、ファイルシステムのノンブロッキング入出力、すなわち select または poll で、たまたまファイルシステムからファイルディスクリプタに出会ったとしても、 少なくとも動作は継続します (あるいは、失敗したとしても、それは selectpoll など)、おそらく最高のパフォーマンスではないにせよ、です。

その一方で epoll はエラーで高速に失敗します ( EPERM 明らかに) で失敗します。 厳密に言えば、これは不正確とは言えません。 単に、サポートされていないことを明示的に示しているに過ぎないのです。 通常、私は明示的な障害条件を称賛しますが、これは (私が知る限り) 文書化されておらず、潜在的に低下したパフォーマンスで動作するだけでなく、完全に壊れたアプリケーションになります。

実際には、私がこれを見た唯一の場所は、stdio と対話するときです。 ユーザーは、通常のファイルから/への stdin または stdout をリダイレクトするかもしれません。 以前は stdin と stdout はパイプであり、epoll によってうまくサポートされていましたが、その後、それは通常のファイルになり、epoll は大声で失敗し、アプリケーションを破壊します。