Vanaf sgcWebSockets 2022.9.0 is er een nieuwe IOHandler voor Linux. Met EPOLL kun je het "one-thread-per-client"-probleem voorkomen waarbij de prestaties sterk afnemen naarmate de server meer verbindingen afhandelt. EPOLL biedt een paar threads die meerdere clients afhandelen. De threads zijn opgeschort en gebruiken geen CPU-cycli totdat er iets te verwerken is.
De EPOLL-IOHandler is alleen beschikbaar in het sgcWebSockets Enterprise-package.
Configuratie
EPOLL voor Linux is een API waarmee je duizenden verbindingen kunt afhandelen met een beperkte threadpool in plaats van één thread per verbinding zoals Indy standaard doet.
Om EPOLL voor Indy-servers in te schakelen, ga je naar de property IOHandlerOptions en selecteer je iohIEPOLL als IOHandler-type.
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 zijn de threads die worden gebruikt voor asynchrone EPOLL-aanvragen (overlapped operations); standaard is de waarde nul, wat betekent dat het aantal threads wordt berekend op basis van het aantal processoren (behalve voor Delphi 7 en 2007, waar het aantal threads op 32 wordt gezet omdat de cpucount-functie niet wordt ondersteund). Je kunt het aantal threads handmatig aanpassen.
2. WorkOpThreads hoef je alleen in te schakelen als je wilt dat verbindingen altijd in dezelfde thread worden verwerkt. Bij EPOLL worden de aanvragen verwerkt door een threadpool, en elke aanvraag (voor dezelfde verbinding) kan in een andere thread worden verwerkt. Als je elke verbinding in dezelfde thread wilt afhandelen, stel in WorkOpThreads het aantal threads in dat deze aanvragen verwerkt. Dit heeft invloed op de prestaties van de server en het wordt alleen aangeraden een waarde groter dan nul in te stellen als je deze functie echt nodig hebt.
EPOLL inschakelen voor Linux-servers wordt aanbevolen wanneer je duizenden verbindingen moet afhandelen; verwerkt je server maximaal 100 gelijktijdige verbindingen, dan kun je het standaard Indy-threadmodel blijven gebruiken.
Prestatietest
Een eenvoudige test laat de verschillen zien tussen het Indy-threadmodel en EPOLL. De test verbindt met de server via het WebSocket-protocol; het CPU-gebruik en het geheugengebruik staan in de onderstaande tabel. Het CPU-gebruikspercentage is gemeten terwijl de server IDLE was.
| Num. Connections | Indy IOHandler Default | 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) |
De Indy-server kon niet meer dan 1024 gelijktijdige verbindingen openen vanwege de beperking van de Select-methode om meer dan 1024 gelijktijdige verbindingen te accepteren. Als we de resultaten tot 1000 verbindingen vergelijken, gebruikte de Indy-standaardserver meer CPU en RAM dan de EPOLL-server. De EPOLL-server gebruikte geen CPU in idle-toestand en ook het geheugengebruik was lager.
De volgende test meet hoe lang het duurt om X clients te verbinden.
| Num. Connections | Indy IOHandler Default | Indy IOHandler EPOLL |
| 1000 | 16,5 seconden | 9,49 seconden |
| 10000 | -- (Failed) | 1 min 55 seconden |
De tests zijn uitgevoerd op Ubuntu 20.0.4 met 2 processoren en 8 GB in een virtuele machine.
EPOLL-documentatie
https://man7.org/linux/man-pages/man7/epoll.7.html
Goede Delphi-projecten die EPOLL implementeren
https://github.com/winddriver/Delphi-Cross-Socket
https://github.com/grijjy/GrijjyFoundation
