Skip to content

Feature/horse core optimization - #507

Merged
regyssilveira merged 13 commits into
HashLoad:masterfrom
regyssilveira:feature/horse-core-optimization
Jul 8, 2026
Merged

Feature/horse core optimization#507
regyssilveira merged 13 commits into
HashLoad:masterfrom
regyssilveira:feature/horse-core-optimization

Conversation

@regyssilveira

Copy link
Copy Markdown
Contributor

Pull Request: Otimizações de Alta Performance e Ciclo de Vida do Core do Horse & Provedor Indy (Fase 1)

📌 Descrição Geral

Este Pull Request implementa otimizações planejadas para o core do framework Horse e seu provedor padrão Indy. As modificações focam em reduzir a latência de tráfego, o overhead de alocação de memória (heap) sob alta concorrência e locks de thread do SO.

Toda a suíte de 24 variantes de testes unitários multiversão (do Delphi 10 Seattle ao Delphi 13 Florence) foi validada, e três novos testes unitários específicos foram desenvolvidos para garantir a cobertura contínua dessas novas APIs públicas.


🛠️ O que foi feito de novo?

1. Lazy-Loading no Core (THorseRequest)

  • Melhoria: Adiamento e prevenção de alocações recorrentes de coleções internas na requisição.
  • Detalhe: A propriedade de controle de sessões (FSessions: THorseSessions) agora é instanciada em modo lazy-loading. Em APIs clássicas REST stateless (onde sessões não são usadas), o overhead de criação e destruição do dicionário de sessões no heap é reduzido a zero.

2. Parâmetros Otimizados no Roteador Radix

  • Melhoria: Remoção de alocações desnecessárias para processamento de caminhos estáticos.
  • Detalhe: Modificamos o Roteador Radix para que a coleção local LParams seja criada somente quando um parâmetro de rota dinâmica (como : ou *) for de fato detectado. Rotas estáticas como /ping, /api/health ou /v1/status agora rodam com zero alocações no heap.

3. Mecanismo de Curto-Circuito sem Exceções (Res.Abort)

  • Melhoria: Interrupção imediata de middlewares/rotas sem a pesada penalidade de CPU do lançamento e tratamento de exceções (raise).
  • Detalhe: Introduzimos o campo FAborted, a propriedade Aborted e o método .Abort em THorseResponse. Ganchos nos despachantes do pipeline (TRadixFlow.Next e TNextCaller.Next) verificam a flag e interrompem a execução de forma limpa. A compatibilidade com exceções clássicas (EHorseException) foi 100% mantida.

4. Arena Allocator Reciclada e Pooled (Horse.Commons)

  • Melhoria: Gestão de memória eficiente para streams e buffers temporários da requisição sem locks de heap do SO.
  • Detalhe: Evoluímos o THorseArenaAllocator original em src/Horse.Commons.pas injetando controle de ciclo de vida seguro de objetos complexos com RegisterObject(AObject). Ao final de cada requisição do pool, a chamada a .Clear zera os ponteiros do buffer de memória contíguo e libera de forma atômica todos os objetos registrados, sem desalocar a memória física da RAM, reduzindo a fragmentação no FastMM4.

5. Escrita Direta de Bytes (Res.Send(TBytes)) e Zero-Copy

  • Melhoria: Bypass de codificações UTF-8 redundantes para serializadores JSON de alta performance.
  • Detalhe: Adicionada a sobrecarga Res.Send(const AContent: TBytes) e a propriedade de sombra BodyBytes em THorseResponse. Provedores de rede (Indy, IOCP, HTTP.sys e Epoll) foram otimizados para despachar diretamente esses bytes no soquete, evitando alocações e conversões de strings UTF-16 temporárias na CPU.

6. Otimizações de Socket & Thread Pool no Provedor Indy (Default)

  • ThreadPool: Integramos TIdSchedulerOfThreadPool para reutilizar as threads ativas do sistema operacional no TIdHTTPServer, eliminando a criação e destruição excessiva de threads por conexão.
  • Sockets: Desativação padrão do algoritmo de Nagle (UseNagle := False) para mitigar atrasos de buffer artificial de 200ms em pacotes pequenos e configuração de Keep-Alive nativo de transporte TCP.

🧪 Cobertura de Testes Unitários (Novos Testes)

Adicionamos cobertura explícita de testes unitários baseados no framework DUnitX:

  1. TTestHorseCoreMiddleware.TestMiddlewareExceptionFreeAbort em tests/src/tests/Tests.Horse.Core.Middleware.pas:
    • Valida se a interrupção via Res.Abort impede a execução das rotas e middlewares subsequentes, mantendo o status HTTP configurado e a flag de abortamento ativa, sem disparar exceções na pilha.
  2. TTestHorseRequestRecycle.TestRequestArenaRecyclingAndObjectLifetime em tests/src/tests/Tests.Horse.Request.Recycle.pas:
    • Garante que objetos registrados no cycle de vida da Arena Allocator da requisição são destruídos automaticamente no .Clear da requisição.
  3. TTestHorseRequestRecycle.TestResponseSendBytesOverload em tests/src/tests/Tests.Horse.Request.Recycle.pas:
    • Valida se a sobrecarga de Send(TBytes) popula corretamente o array BodyBytes na resposta HTTP.

📈 Matriz de Testes Multiversão (24/24 Passou Verde)

Compilador / IDE Provedor de Rede Compilação Testes Unitários
Delphi 10 Seattle Todos (Default, HttpSys, IOCP +/- Radix) SUCESSO PASSOU
Delphi 11 Alexandria Todos (Default, HttpSys, IOCP +/- Radix) SUCESSO PASSOU
Delphi 12 Athens Todos (Default, HttpSys, IOCP +/- Radix) SUCESSO PASSOU
Delphi 13 Florence Todos (Default, HttpSys, IOCP +/- Radix) SUCESSO PASSOU

⚠️ Impactos e Retrocompatibilidade

  • Não foram detectadas quebras de compatibilidade sintática nem funcional para usuários do Horse. As novas APIs de bytes e aborto são opcionais e as exceções clássicas continuam operando normalmente.
  • A classe THorseArenaAllocator foi estendida sem alterar suas propriedades originais (Buffer, Start, Len), garantindo a preservação total das árvores de rotas que já a utilizavam.

…aded, avoiding heap allocations on static routes
… avoiding heap allocation on stateless API requests
… Res.Abort and Res.Aborted check in middlewares pipeline
…-loaded recycled memory allocator in THorseRequest
…, and Epoll providers to bypass string-to-utf8 encoding when raw bytes are passed
… and configure socket keep-alive values in Indy-based providers
…st and Horse.Response; merge Arena changes directly into Horse.Commons
…TBytes) shadow array, and THorseRequest.Arena object lifecycle registration
… (OPTIONS) and Authentication (Auth) middleware flows
@regyssilveira
regyssilveira merged commit b1e0941 into HashLoad:master Jul 8, 2026
@regyssilveira
regyssilveira deleted the feature/horse-core-optimization branch July 8, 2026 20:59
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.

1 participant