Server Indy - IOCP Windows (2 / 3)

· Funzionalità

Da sgcWebSockets 2022.9.0 l'IOHandler IOCP del server Indy è stato riscritto da zero e le prestazioni sono state migliorate. L'IOHandler IOCP è disponibile solo nel pacchetto sgcWebSockets Enterprise.

Usando IOCP 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.

Configurazione 

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

Server.IOHandlerOptions.IOHandlerType := iohIOCP;
Server.IOHandlerOptions.IOCP.IOCPThreads := 0; // the number of IOCP threads will be calculated automatically using the number of processors.
Server.IOHandlerOptions.IOCP.WorkOpThreads := 0;

1. IOCPThreads sono i thread usati per le richieste asincrone IOCP (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).

2. WorkOpThreads deve essere abilitato solo se vuoi che le connessioni vengano sempre elaborate nello stesso thread. Quando usi IOCP, 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 IOCP per i server Windows è 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 IOCP. 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 IOCP
100 0% (4.1MB) 0% (3.9MB)
5000% (17.1MB)0% (7.7MB)
10000% (32.2MB)0% (12.4MB)
15007.3% (46.8MB)0% (17.1MB)
200015.4% (61.6MB)0% (21.9MB)
250051.9% (76.5MB)0% (26.5MB)
300068.8% (91.7MB)0% (31.2MB)
350072.3% (106MB)0% (35.9MB)

Il server Indy ha iniziato a subire rallentamenti con più di 3000 connessioni concorrenti, molto probabilmente a causa del context switch dei thread e l'utilizzo della CPU era molto alto mentre il server era in idle.

Il server IOCP non usava CPU mentre era in stato di idle e anche il consumo di memoria era più basso.

Il test successivo misura quanto tempo ci vuole per connettere 3000 client, ognuno invia un messaggio quando si connette al server e il server fa l'echo di questo messaggio.

IOHandler Indy predefinito IOHandler Indy IOCP
Connetti 3000 client e fai l'echo del messaggio 15,32 secondi 6,89 secondi

I test di prestazioni sono stati eseguiti su Windows Server 2022 con 16 core e 32GB di RAM.