Perf/epoll zero allocation - #478
Merged
viniciussanchez merged 2 commits intoJun 26, 2026
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
perf(epoll): Zero-Allocation HTTP Parser e Otimizações de Concorrência
Este PR introduz otimizações profundas de performance no Provider Epoll (Linux) do Horse, importadas e adaptadas a partir das melhorias de parsing HTTP e gerência de I/O do framework Dext. Além disso, corrige um vazamento de memória crítico na recepção de cabeçalhos e otimiza a pilha de conexões sob concorrência extrema (>1000 conexões simultâneas).
🛠️ Alterações Introduzidas
1. Zero-Allocation HTTP Parser
TDictionary<string, THeaderSegment>para armazenamento de offsets por arrays dinâmicos nativos baseados em records (THeaderSegments = TArray<THeaderSegment>).FResolvedHeaders) é mantido na requisição apenas para as chaves explicitamente consultadas.2. Correção de Memory Leak Crítico
outde dicionários gerados no parser sobrescrevia o ponteiro interno de cabeçalhos do contexto sem liberar a instância anterior. Com a mudança para arrays dinâmicos (TArray), a gerência de memória passa a ser nativa por contagem de referência do Delphi, eliminando o vazamento por completo.3. Elevação do TCP Listen Backlog
InternalListenpara evitar descartes prematuros de pacotes pelo kernel do Linux (syn floodinglocal) durante surtos de requisições concorrentes.THorse.ListenQueue := 4096de modo a elevar o limite de escuta padrão do Indy (que por padrão é de apenas 15 conexões no Delphi).📊 Resultados do Teste de Estresse (Benchmark Real)
Os testes foram executados via Docker no Linux (Ubuntu 22.04) simulando 1000 conexões simultâneas e 20.000 requisições HTTP GET
/pingem rede virtual bridge isolada.Cenário 1: Conexões Curtas (Sem Keep-Alive)
Abre e fecha um socket TCP completo para cada requisição.
Cenário 2: Conexões Persistentes (Com Keep-Alive)
Reutiliza conexões TCP abertas via socket Keep-Alive.
Principais Conclusões dos Testes:
🔍 Arquivos Modificados
src/Horse.Provider.Epoll.pas— Refatoração para zero-allocation e aumento do backlog.samples/delphi/console/Console.dpr— Elevação do listen queue padrão do Indy.