Server Indy - EPOLL Linux (3 / 3)

· Funzionalità

Da sgcWebSockets 2022.9.0 è disponibile un nuovo IOHandler per Linux, usando EPOLL puoi evitare il problema "un thread per client" in cui le prestazioni diminuiscono molto man mano che il server gestisce più connessioni. IOCP fornisce alcuni thread che gestiscono più client. I thread sono sospesi e non usano cicli di CPU finché non c'è qualcosa da elaborare.

L'IOHandler EPOLL è disponibile solo nel pacchetto sgcWebSockets Enterprise.


Configurazione 

EPOLL per Linux è un'API che permette di gestire migliaia di connessioni usando un pool di thread limitato invece di usare un thread per connessione come fa Indy per impostazione predefinita.

Per abilitare EPOLL per i server Indy, vai alla proprietà IOHandlerOptions e seleziona iohIEPOLL come tipo di IOHandler.

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 sono i thread usati per le richieste asincrone EPOLL (operazioni overlapped), per impostazione predefinita il valore è zero, il che significa che il numero di thread viene calcolato usando il numero di processori (eccetto per Delphi 7 e 2007 dove il numero di thread è impostato a 32 perché la funzione cpucount non è supportata). Puoi regolare manualmente il numero di thread.

2. WorkOpThreads deve essere abilitato solo se vuoi che le connessioni vengano sempre elaborate nello stesso thread. Quando usi EPOLL, le richieste vengono elaborate da un pool di thread, e ogni richiesta (per la stessa connessione) può essere elaborata in thread diversi. Se vuoi gestire ogni connessione nello stesso thread imposta in WorkOpThreads il numero di thread usati per gestire queste richieste. Questo impatta sulle prestazioni del server ed è consigliato impostare un valore maggiore di zero solo se hai bisogno di questa funzionalità.

Abilitare EPOLL per i server Linux è consigliato quando devi gestire migliaia di connessioni, se il tuo server gestisce al massimo solo 100 connessioni concorrenti puoi rimanere con il modello a thread Indy predefinito.

Test di prestazioni 

Un semplice test mostrerà le differenze tra il modello a thread Indy e EPOLL. Il test si connetterà al server usando il protocollo websocket e l'utilizzo della CPU e il consumo di memoria verranno mostrati nella tabella seguente. La % di utilizzo della CPU è mentre il server è in IDLE.

N. connessioni IOHandler Indy predefinito IOHandler Indy EPOLL
100 1% (1.4MB) 0% (1.4MB)
5004% (5.6MB)0% (4.8MB)
100010% (10.5MB)0% (8.9MB)
1500-- (Fallito)0% (13.3MB)
2000-- (Fallito)0% (17.4MB)

Il server Indy non poteva aprire più di 1024 connessioni concorrenti, a causa della limitazione del metodo Select ad accettare più di 1024 connessioni concorrenti. Confrontando i risultati fino a 1000 connessioni, il server Indy predefinito usava più CPU e più RAM del server EPOLL. Il server EPOLL non usava CPU mentre era in idle e anche il consumo di memoria era più basso.

Il test successivo misura quanto tempo ci vuole per connettere X client.

N. connessioni IOHandler Indy predefinito IOHandler Indy EPOLL
1000 16,5 secondi 9,49 secondi
10000-- (Fallito)1min 55 secondi

I test sono stati eseguiti su Ubuntu 20.0.4 con 2 processori e 8GB in esecuzione su una macchina virtuale.

Documentazione EPOLL

https://man7.org/linux/man-pages/man7/epoll.7.html

Ottimi progetti Delphi che implementano EPOLL

https://github.com/winddriver/Delphi-Cross-Socket
https://github.com/grijjy/GrijjyFoundation