Se você desenvolve em Delphi e acompanha a evolução da plataforma, já sabe que o suporte a Linux abriu um mundo de novas possibilidades para microsserviços e APIs web modernas. Contudo, rodar no Linux é apenas metade do caminho. A grande questão é: como extrair a máxima performance que o kernel do Linux tem a oferecer, escrevendo código Delphi puro?
No desenvolvimento web com Delphi, o padrão da indústria por muitos anos foi o uso do Indy (Internet Direct). Embora o Indy seja uma biblioteca extremamente madura e robusta, seu modelo de concorrência baseado em “Thread-per-Connection” encontra um limite físico rígido sob alta concorrência.
Para romper essa barreira e aproximar o ecossistema Delphi de tecnologias de alta performance como .NET Core, Go e Rust, o Dext Framework introduziu uma engine nativa baseada no Epoll do Linux.
Neste artigo, detalhamos o design de concorrência das duas soluções, a metodologia de testes aplicada em ambiente isolado e os números dos benchmarks comparativos que alcançaram a marca de mais de 100.000 requisições por segundo (em picos) e 19.900 req/s em média sustentada em contêineres Ubuntu 22.04.
1. Indy vs. Epoll: Dois Mundos de Concorrência
Para entender a diferença de performance, precisamos analisar como essas duas engines lidam com conexões de rede em nível de sistema operacional.
O Modelo Indy: Uma Thread por Conexão (Bloqueante)
O Indy utiliza operações de socket síncronas e bloqueantes. Para cada novo cliente que se conecta ao servidor:
- O servidor aceita a conexão.
- Uma nova thread (ou uma thread reciclada do Thread Pool) é dedicada exclusivamente àquela conexão.
- Essa thread fica travada (bloqueada) esperando dados do cliente.
O problema sob carga: Se você tem 1.000 clientes simultâneos sob estresse de rede, precisa de 1.000 threads ativas. O sistema operacional consome uma quantidade massiva de recursos fazendo o chaveamento de contexto (Thread Thrashing) e alocando memória para a pilha de cada thread. A performance cai drasticamente e a latência sobe exponencialmente.
O Modelo Epoll: Multiplexação de I/O por Eventos (Não Bloqueante)
O Epoll é um mecanismo exclusivo do kernel do Linux projetado para lidar com I/O assíncrono e de altíssima concorrência.
- Em vez de termos uma thread por conexão, os sockets são configurados como não bloqueantes (
O_NONBLOCK). - Uma ou poucas threads especiais (conhecidas como Reactor) registram todos os descritores de sockets (
FD) no mecanismo de monitoramento do kernel do Linux viaepoll_wait. - Quando o kernel detecta que um socket específico recebeu dados do cliente (evento
EPOLLIN) ou está pronto para enviar dados (eventoEPOLLOUT), ele notifica a thread do reactor. - O reactor rapidamente lê/escreve no socket e delega o processamento da requisição para um pool reduzido de threads de CPU (usando
TTaskda Parallel Programming Library do Delphi).
O resultado? O servidor gerencia dezenas de milhares de conexões abertas concorrentemente usando o número ideal de threads idêntico ao número de núcleos físicos da CPU, reduzindo o consumo de memória e a latência a patamares mínimos.
2. O que foi feito: O Trabalho de Engenharia no Dext
Para viabilizar este teste comparativo e assegurar a robustez do Dext no Linux, passamos por três etapas fundamentais de desenvolvimento e infraestrutura:
- Ajuste de Pipelines Não-Interativos (
-no-wait): O executável original de benchmarks do Dext (Dext.Benchmarks) lia a entrada do console viaReadlnpara se manter ativo após a inicialização. Em ambientes automatizados ou contêineres que rodam em background, o console é redirecionado, o que fazia o servidor encerrar imediatamente. Implementamos uma flag de linha de comando (-no-wait/--no-wait) que substitui a leitura de teclado por um loop passivo deSleep(1000). - Automação de Compilação com
dcclinux64: Desenvolvemos um script PowerShell (build_linux.ps1) para orquestrar a compilação cruzada no Windows para Linux. O script mapeia todas as units do Dext, as dependências externas e aponta para o SDK de desenvolvimento do Ubuntu (ubuntu22.04.sdk), garantindo a correta linkagem estática contra as bibliotecas nativas de C (libc.a,libpthread.a, etc.) fornecidas pelo Delphi. - Sincronização de Assinaturas de Contexto: Atualizamos os ambientes de mocks do benchmark (
TMockHttpContext) para implementar a assinatura da interface mais recente deIHttpContextdo core do Dext, mantendo a suite alinhada aos padrões de produção do framework.
3. Metodologia de Testes Aplicada
Para que os resultados fossem precisos e refletissem o comportamento real de produção, estabelecemos a seguinte metodologia:
- Isolamento de Ambiente: Os testes foram executados dentro de um contêiner Docker limpo (
ubuntu:22.04) rodando no Windows sobre o subsistema WSL2 (Windows Subsystem for Linux). Isso garante que o sistema de arquivos e a biblioteca libc sejam puramente Linux, idênticos a uma VPS de produção. - Ajuste de Limites do Kernel (File Descriptors): Sob estresse intenso, o número padrão de conexões simultâneas permitidas por processo no Linux (geralmente
1024arquivos abertos) é rapidamente superado. Rodamos o contêiner Docker configurando--ulimit nofile=65535:65535para elevar os limites de sockets abertos em nível de kernel, evitando falhas prematuras de rede. - Instalação das Dependências do Sistema: Embora o servidor responda a requisições HTTP estáticas, a unit de ORM do Dext é inicializada no startup (
initialization) do binário. Garantimos a instalação delibsqlite3-devno contêiner para que o banco em memória SQLite pudesse ser alocado sem problemas. - Ferramenta de Carga: Utilizamos o
bombardier, uma das ferramentas de benchmark HTTP mais rápidas e eficientes do mercado (escrita em Go). Simulamos uma carga agressiva de 125 conexões simultâneas mantidas de forma ininterrupta por 10 segundos contra o endpoint/ping(que responde um texto estático'pong'). - Intervalo e Isolamento de Processos: Cada engine (Epoll e Indy) foi executada e testada separadamente. O script de testes aguarda
3segundos para a inicialização e estabilização de cada servidor antes de iniciar a carga. Ao término, o processo é encerrado de forma forçada (kill) e um intervalo de2segundos é respeitado para liberar as portas TCP do kernel antes da inicialização do próximo teste.
4. Os Números: A Prova de Fogo no Linux
Abaixo estão os dados finais obtidos diretamente das execuções monitoradas no contêiner Ubuntu:
Tabela Comparativa de Performance
| Métrica de Rede | Dext com Epoll (Multiplexado) | Dext com Indy (Thread-per-Conn) | Ganho Real |
|---|---|---|---|
| Vazão Média (Reqs/sec) | 19.909,36 req/s | 611,48 req/s | ~32.5x mais veloz |
| Latência Média | 6,27 ms | 202,50 ms | ~32.3x menos latência |
| Latência Máxima | 42,52 ms | 3.630,00 ms (3,63s) | Muito mais estável |
| Requisições de Sucesso (2xx) | 199.042 | 6.241 | +192.801 requisições |
| Erros de Conexão | 0 | 0 | 100% de estabilidade |
| Vazão de Dados (Throughput) | 2,18 MB/s | 142,38 KB/s | Melhor uso da rede |
Nota: Em picos de teste de carga, a engine Epoll chegou a registrar 200.674,63 req/s.
O que esses dados significam na prática?
- Redução de Gargalos de CPU: Enquanto a latência do Indy disparava para mais de 3,6 segundos devido à disputa e sobrecarga de criação de threads na CPU, o Epoll manteve o tempo de resposta médio em confortáveis 6,27 ms, com picos máximos de apenas 42 ms.
- Escalabilidade Exponencial: Em sistemas de produção, o Epoll permite que o mesmo hardware físico atenda a dezenas de milhares de clientes de forma concorrente sem a necessidade de escalar a infraestrutura horizontalmente de imediato.
- Padrão de Microsserviço Moderno: Com quase 20k RPS em média por contêiner, o Delphi se coloca no topo do ranking de performance para aplicações nativas em Linux.
Conclusão
A otimização de concorrência com o Epoll no Dext Framework prova que o compilador Linux do Delphi 12, quando aliado às chamadas nativas do kernel da forma correta, é um gigante pronto para rodar nos maiores ambientes de produção do mercado.
Você não precisa reescrever o seu backend em outras linguagens para obter alta vazão e estabilidade extrema em ambientes em nuvem ou contêineres Kubernetes. O Delphi é, e continua sendo, uma das linguagens nativas mais rápidas do mundo.
O código-fonte completo do Dext e os scripts de benchmark estão disponíveis sob licença Apache 2.0.
Se você quer conferir ou rodar os testes na sua máquina física Linux, basta clonar o repositório oficial do Dext e conferir os scripts presentes na pasta Benchmarks/.
Descubra mais sobre Régys Borges da Silveira
Assine para receber nossas notícias mais recentes por e-mail.
Dê-nos sua opinião, seu comentário ajuda o site a crescer e melhorar a qualidade dos artigos.