Ab sgcWebSockets 2022.9.0 gibt es einen neuen IOHandler für Linux. Mit EPOLL vermeidest du das "Ein-Thread-pro-Client"-Problem, bei dem die Leistung stark einbricht, je mehr Verbindungen der Server verarbeitet. EPOLL stellt wenige Threads bereit, die viele Clients bedienen. Die Threads sind suspendiert und verbrauchen keine CPU-Zyklen, solange nichts zu tun ist.
Der EPOLL-IOHandler ist nur im sgcWebSockets-Enterprise-Paket verfügbar.
Konfiguration
EPOLL für Linux ist eine API, mit der du tausende Verbindungen über einen begrenzten Thread-Pool verarbeiten kannst, anstatt wie Indy standardmäßig einen Thread pro Verbindung zu verwenden.
Um EPOLL für Indy-Server zu aktivieren, gehe zur Eigenschaft IOHandlerOptions und wähle iohIEPOLL als IOHandler-Typ.
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 sind die Threads für asynchrone EPOLL-Anfragen (überlappte Operationen). Standardwert ist null, was bedeutet, dass die Threadanzahl anhand der Prozessorzahl berechnet wird (außer bei Delphi 7 und 2007, wo der Wert auf 32 gesetzt wird, da die Funktion cpucount dort nicht unterstützt wird). Du kannst die Threadanzahl manuell anpassen.
2. WorkOpThreads muss nur aktiviert werden, wenn Verbindungen immer im selben Thread verarbeitet werden sollen. Bei EPOLL werden Anfragen von einem Thread-Pool verarbeitet, und jede Anfrage (für dieselbe Verbindung) kann in unterschiedlichen Threads laufen. Möchtest du jede Verbindung im selben Thread halten, setze in WorkOpThreads die Anzahl der Threads, die diese Anfragen verarbeiten. Das beeinflusst die Server-Leistung; es wird nur empfohlen, einen Wert größer null zu setzen, wenn du diese Funktion wirklich brauchst.
EPOLL für Linux-Server wird empfohlen, wenn du tausende Verbindungen verarbeiten musst. Bei höchstens 100 gleichzeitigen Verbindungen kannst du beim Standard-Indy-Thread-Modell bleiben.
Leistungstest
Ein einfacher Test zeigt die Unterschiede zwischen dem Indy-Thread-Modell und EPOLL. Der Test verbindet sich per WebSocket-Protokoll zum Server, und CPU-Auslastung sowie Speicherverbrauch werden in folgender Tabelle dargestellt. Die CPU-Auslastung wird gemessen, während der Server im Leerlauf ist.
| Anz. Verbindungen | Indy IOHandler Standard | 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 | -- (fehlgeschlagen) | 0% (13.3MB) |
| 2000 | -- (fehlgeschlagen) | 0% (17.4MB) |
The Indy server could not open more than 1024 concurrent connections, due to the limitation of Select method to accept more than 1024 concurrent connections. Comparing the results till 1000 connections, the Indy Default Server was using more cpu and more RAM than EPOLL server. Der EPOLL-Server verbrauchte im Leerlauf keine CPU, und auch der Speicherverbrauch war geringer.
Der nächste Test misst, wie lange das Verbinden von X Clients dauert.
| Anz. Verbindungen | Indy IOHandler Standard | Indy IOHandler EPOLL |
| 1000 | 16,5 Sekunden | 9,49 Sekunden |
| 10000 | -- (fehlgeschlagen) | 1 Min 55 Sekunden |
Die Tests liefen auf einem Ubuntu 20.0.4 mit 2 Prozessoren und 8 GB in einer virtuellen Maschine.
EPOLL-Dokumentation
https://man7.org/linux/man-pages/man7/epoll.7.html
Großartige Delphi-Projekte mit EPOLL-Implementierung
https://github.com/winddriver/Delphi-Cross-Socket
https://github.com/grijjy/GrijjyFoundation
