Indy Servers - IOCP Windows (2 / 3)

· Recursos

A partir do sgcWebSockets 2022.9.0, o IOCP IOHandler do servidor Indy foi reescrito do zero com desempenho aprimorado. O IOCP IOHandler está disponível apenas no pacote sgcWebSockets Enterprise.

Usando IOCP, você pode evitar o problema "uma thread por cliente", em que o desempenho cai significativamente à medida que mais conexões são tratadas pelo servidor. O IOCP utiliza poucas threads para atender múltiplos clientes. As threads ficam suspensas e não consomem ciclos de CPU até que haja algo a processar.

Configuração 

Para habilitar o IOCP nos servidores Indy, vá até a propriedade IOHandlerOptions e selecione iohIOCP como tipo de 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 são as threads usadas para requisições assíncronas IOCP (operações overlapped). Por padrão, o valor é zero, o que significa que o número de threads é calculado automaticamente com base no número de processadores (exceto para Delphi 7 e 2007, onde o número de threads é definido como 32, pois a função cpucount não é suportada).

2. WorkOpThreads deve ser habilitado apenas se você quiser que as conexões sejam sempre processadas na mesma thread. Ao usar IOCP, as requisições são processadas por um pool de threads, e cada requisição (da mesma conexão) pode ser processada em threads diferentes. Se quiser tratar cada conexão sempre na mesma thread, defina em WorkOpThreads o número de threads usadas para essas requisições. Isso impacta o desempenho do servidor e só é recomendado definir um valor maior que zero se você realmente precisar desse recurso.

Habilitar o IOCP em servidores Windows é recomendado quando você precisa lidar com milhares de conexões. Se seu servidor trata no máximo 100 conexões simultâneas, você pode manter o modelo padrão de threads do Indy.

Teste de Desempenho 

Um teste simples mostrará as diferenças entre o modelo de threads do Indy e o IOCP. O teste conectará ao servidor usando o protocolo WebSocket, e o uso de CPU e o consumo de memória serão mostrados na tabela a seguir. O percentual de uso de CPU é medido enquanto o servidor está em estado IDLE.

Num. de Conexões Indy Default IOHandler Indy IOCP IOHandler
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)

O servidor Indy começou a apresentar lentidão com mais de 3.000 conexões simultâneas, provavelmente devido à troca de contexto de threads, e o uso de CPU era muito alto mesmo com o servidor em modo idle.

O servidor IOCP não consumia CPU no estado idle e o consumo de memória também era menor.

O próximo teste mede quanto tempo leva para conectar 3.000 clientes, cada um enviando uma mensagem ao conectar-se ao servidor, que ecoa essa mensagem.

Indy Default IOHandler Indy IOCP IOHandler
Conectar 3000 clientes e ecoar mensagem 15.32 seconds 6.89 seconds

Os testes de desempenho foram realizados em um Windows Server 2022 com 16 núcleos e 32 GB de RAM.