Skip to content

Perf/epoll zero allocation - #479

Merged
viniciussanchez merged 3 commits into
HashLoad:masterfrom
regyssilveira:perf/epoll-zero-allocation
Jun 26, 2026
Merged

Perf/epoll zero allocation#479
viniciussanchez merged 3 commits into
HashLoad:masterfrom
regyssilveira:perf/epoll-zero-allocation

Conversation

@regyssilveira

Copy link
Copy Markdown
Contributor

perf(epoll): otimização de memória do request e parser HTTP zero-allocation

Descrição

Este PR porta melhorias de performance e redução de consumo de memória heap do driver Epoll do framework Dext para o provider Epoll do Horse (Horse.Provider.Epoll.pas).

As mudanças focam em diminuir o footprint de memória de cada conexão ativa sob alta carga concorrente e mitigar o allocation churn de strings na heap durante o parsing da Request Line.


Mudanças Introduzidas

1. Otimização de Memória no Epoll Request (TEpollRawRequest)

  • Liberação Antecipada de Buffers: Modificamos o construtor Create para aceitar o buffer de conexão como parâmetro var e clonar estritamente a parte útil do cabeçalho (ABodyOffset).
  • Logo após a cópia, chamamos TBufferPool.Release(ABuffer) imediatamente de dentro do construtor, devolvendo o buffer original de 8KB ao pool estático de forma imediata (segundos antes da conclusão do processamento da rota do usuário).
  • Redução do Heap no Request: O request agora mantém apenas os bytes do cabeçalho sob medida na heap, em vez de prender o buffer de leitura de 8KB inteiro. A liberação no destruidor foi removida, deixando a gerência do array sob responsabilidade da runtime do Delphi/FPC.

2. Otimização do HTTP Parser (THorseHttpParser - Zero-Allocation)

  • Métodos HTTP Otimizados (GetMethodString): Introduzimos casamento de padrões direto nos bytes do buffer para os verbos mais comuns (GET, POST, PUT, DELETE, HEAD, PATCH, OPTIONS), retornando strings constantes e evitando chamadas de decodificação UTF-8 (TEncoding.UTF8.GetString) na heap.
  • Eliminação do RawLine: Removemos a string temporária RawLine: AnsiString e as chamadas ao método Copy do Delphi, extraindo APath, AQuery e AVersion via TEncoding.UTF8.GetString diretamente sobre os offsets reais do buffer.
  • Fast-Path para Path Raiz (/): Requisições direcionadas para o path raiz / agora recebem o literal estático '/' sem alocar nenhuma string.

3. Compatibilidade Cross-Compiler (Delphi 12 & FPC)

  • Adicionamos diretivas condicionais de compilador no método CloseConnection para manter a compatibilidade de Linker e compilação do TInterlocked nativo em ambos os ambientes:
    {$IFDEF FPC}
    if InterlockedCompareExchange(AContext.FClosed, 1, 0) <> 0 then
    {$ELSE}
    if TInterlocked.CompareExchange(AContext.FClosed, 1, 0) <> 0 then
    {$ENDIF}

@viniciussanchez
viniciussanchez merged commit 47ed472 into HashLoad:master Jun 26, 2026
@regyssilveira
regyssilveira deleted the perf/epoll-zero-allocation branch June 30, 2026 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants