sgcWebSockets 2022.9.0 から、Linux 用の新しい IOHandler が追加されました。EPOLL を使用すると、サーバーが処理する接続数が増えるとパフォーマンスが大幅に低下する「クライアントごとに 1 スレッド」の問題を回避できます。IOCP は複数のクライアントを扱う少数のスレッドを提供します。スレッドは中断され、処理すべきものがあるまで CPU サイクルを消費しません。
EPOLL IOHandler は sgcWebSockets Enterprise パッケージでのみ利用可能です。
設定
Linux 用 EPOLL は、Indy がデフォルトで行うように接続ごとにスレッドを使う代わりに、限定的なスレッドプールで数千の接続を処理できる API です。
Indy サーバーで EPOLL を有効にするには、IOHandlerOptions プロパティに移動し、IOHandler Type として iohIEPOLL を選択します。
Server.IOHandlerOptions.IOHandlerType := iohEPOLL; Server.IOHandlerOptions.EPOLL.EPOLLThreads := 0; // the number of EPOLL threads will be calculated automatically using the number of processors. Server.IOHandlerOptions.EPOLL.WorkOpThreads := 0;
1. EPOLLThreads は EPOLL 非同期リクエスト(オーバーラップド操作)に使用されるスレッドです。デフォルト値はゼロで、これはプロセッサー数を使って自動計算されることを意味します(Delphi 7 と 2007 では cpucount 関数がサポートされないため 32 に設定されます)。スレッド数を手動で調整できます。
2. WorkOpThreads は、接続を常に同じスレッドで処理したい場合のみ有効にする必要があります。EPOLL を使用する場合、リクエストはスレッドプールで処理され、(同じ接続の)各リクエストは異なるスレッドで処理される可能性があります。すべての接続を同じスレッドで処理したい場合は、WorkOpThreads にこれらのリクエストの処理に使用するスレッド数を設定してください。これはサーバーのパフォーマンスに影響するため、この機能が必要な場合のみゼロより大きい値を設定することが推奨されます。
Linux サーバーで EPOLL を有効にすることが推奨されるのは、数千の接続を処理する必要がある場合です。サーバーが最大 100 個の同時接続のみを処理する場合は、デフォルトの Indy スレッドモデルのままでも問題ありません。
パフォーマンステスト
シンプルなテストで Indy スレッドモデルと EPOLL の違いを示します。テストでは websocket プロトコルを使用してサーバーに接続し、CPU 使用率とメモリ消費量を以下の表に示します。CPU 使用率はサーバーがアイドル状態のときの値です。
| 接続数 | Indy IOHandler デフォルト | Indy IOHandler EPOLL |
| 100 | 1% (1.4MB) | 0% (1.4MB) |
| 500 | 4% (5.6MB) | 0% (4.8MB) |
| 1000 | 10% (10.5MB) | 0% (8.9MB) |
| 1500 | -- (Failed) | 0% (13.3MB) |
| 2000 | -- (Failed) | 0% (17.4MB) |
Select メソッドの制限により 1024 を超える同時接続を受け付けられないため、Indy サーバーは 1024 を超える同時接続を開くことができませんでした。1000 接続までの結果を比較すると、Indy のデフォルトサーバーは EPOLL サーバーよりも CPU と RAM を多く使用していました。 EPOLL サーバーはアイドル状態のときに CPU を使用せず、メモリ消費量もより低いものでした。
次のテストでは、X クライアントの接続にかかる時間を測定します。
| 接続数 | Indy IOHandler デフォルト | Indy IOHandler EPOLL |
| 1000 | 16.5 seconds | 9.49 seconds |
| 10000 | -- (Failed) | 1min 55 seconds |
テストは、仮想マシンで動作する 2 プロセッサー・8GB の Ubuntu 20.0.4 で実施しました。
EPOLL ドキュメント
https://man7.org/linux/man-pages/man7/epoll.7.html
EPOLL を実装した優れた Delphi プロジェクト
https://github.com/winddriver/Delphi-Cross-Socket
https://github.com/grijjy/GrijjyFoundation
