No desenvolvimento de microsserviços modernos, a velocidade de comunicação entre APIs é um dos fatores mais críticos para a escalabilidade de toda a infraestrutura. É por isso que o gRPC (baseado em HTTP/2 e Protocol Buffers) tornou-se o padrão ouro de comunicação interna em gigantes da tecnologia, superando o tradicional REST/JSON em termos de vazão e uso de banda.
Recentemente, no ecossistema do Horse — o micro-framework web preferido dos desenvolvedores Delphi e Lazarus —, iniciamos uma jornada intensa de engenharia de software para construir um provedor gRPC nativo (Cleartext h2c) capaz de bater de frente com os gigantes do mercado, como C#, Go e Rust. O resultado? Alcançamos a marca de 9.773 QPS (requisições por segundo) com uma latência média de apenas 20ms no host local.
Neste artigo, vou revelar os bastidores técnicos de como implementamos otimizações em nível de hardware, CPU, alocação de heap e concorrência para atingir essa marca histórica de performance no Delphi.
1. O Gargalo do RTTI e a Solução via CodeGen (Serialização Estática)
O maior inimigo dos servidores de alto throughput em Object Pascal é a reflexão em tempo de execução (RTTI) tradicional. Ler propriedades dinamicamente de classes para converter em bytes protobuf consome muitos ciclos de CPU e gera o terrível boxing/unboxing de tipos genéricos (como o uso de TValue).
Para resolver isso na raiz, o compilador CLI do gRPC do Horse (horse-pb-compiler) foi estendido. Agora, ao compilar um esquema .proto, a ferramenta injeta métodos estáticos compilados de serialização direta nas classes geradas:
procedure TUserResponse.Serialize(AStream: TStream);
begin
// Escrita binária sequencial direta na CPU, sem passar por RTTI!
WriteVarint(1, Fid, AStream);
WriteString(2, Fname, AStream);
WriteString(3, Femail, AStream);
end;
Quando o servidor gRPC do Horse processa uma mensagem, ele detecta a presença desses métodos e desvia 100% do motor de reflexão, executando a escrita na placa de rede puramente via código compilado nativo. Isso resultou em um ganho de até 500% de performance na CPU.
2. Fallback Ultrarápido: Aritmética de Ponteiros via Offsets
Para cenários onde o desenvolvedor prefere declarar os contratos de forma manual (Code-First) sem gerar as units pelo compilador CLI, projetamos um fallback rápido de RTTI híbrida.
Em vez de chamar o método lento TRttiProperty.SetValue a cada requisição, a RTTI do Horse calcula o offset físico de memória onde o campo reside na heap do objeto e cacheia essa informação. Durante a escrita, o framework realiza aritmética direta de ponteiros:
// Gravação direta no endereço da Heap, desviando da reflexão de propriedades
PByte(ObjInstance) + FieldOffset := Pointer(ValueBytes);
3. THorseBufferPool: Zerando as Alocações de Heap por Conexão
Se você rodar um servidor sob estresse concorrente extremo com milhões de requisições, o alocador de memória do sistema operacional (e até o FastMM) começará a sofrer de contenda de threads (lock contention) e fragmentação de memória, degradando a performance ao longo dos dias.
Criamos o THorseBufferPool, um pool concorrente thread-safe global que mantém buffers de 64KB pré-alocados. Quando uma nova conexão gRPC entra no pool de threads de trabalho, ela apenas “aluga” um buffer do pool e, ao concluir, devolve-o imediatamente. Isso zerou a alocação de byte arrays por conexão na heap do SO, resultando em um consumo estável, linear e em Zero Leaks (vazamentos de memória) sob estresse continuado.
4. Singleton DI vs. Call Scope
Demos ao desenvolvedor a flexibilidade total de escolher o ciclo de vida dos seus microsserviços. O provedor gRPC aceita dois modelos de injeção de dependências:
- Call Scope (Padrão): A classe de serviço é instanciada e destruída isoladamente por chamada, garantindo isolamento absoluto de conexões de banco de dados (ideal para REST-gateways).
- Singleton DI: Você registra uma única instância compartilhada e persistente do serviço gRPC. Isso elimina totalmente o overhead de instanciação a cada chamada de rede, maximizando o reuso de recursos em microsserviços de mensageria.
5. THorseChannel<T>: gRPC Streaming Nativo Inspirado em Go
gRPC não se limita a enviar um request e aguardar um response (Unary). Para suportar transmissões de dados pesadas (como listagens ou arquivos), implementamos o suporte a gRPC Streaming.
Para isso, criamos o THorseChannel<T>, uma fila concorrente thread-safe inspirada nos canais do Go. O canal usa sinais de eventos do sistema operacional (TSimpleEvent) para suspender a thread de rede de forma passiva, consumindo zero ciclos de CPU enquanto não há dados:
var
LChannel: THorseChannel<TUserResponse>;
begin
LChannel := THorseChannel<TUserResponse>.Create;
// A thread de negócio lê do banco e escreve no canal:
LChannel.Write(UserObj);
// A thread do socket do Horse lê o canal e envia na hora como frame DATA HTTP/2:
LChannel.ReadObject(LItem);
end;
Com essa técnica, o consumo de RAM do servidor permanece constante (próximo de zero) mesmo que você esteja transferindo 10 milhões de registros, pois não acumulamos dados na heap do servidor antes de enviar.
📊 O Comparativo de Performance no Mercado
Rodando em ambiente de testes localhost (Intel i7 com 200 conexões concorrentes simultâneas batendo carga de 50.000 requisições), coletamos os dados consolidados em relação aos principais ecossistemas do mercado gRPC:
| Tecnologia / Framework | Linguagem | QPS Médio | Latência Média | Consumo de RAM / Heap |
|---|---|---|---|---|
| Rust (Tonic) | Rust | ~12.500 QPS | 12 ms | Extremamente Baixo |
| Go (grpc-go) | Go | ~11.200 QPS | 15 ms | Baixo |
| .NET gRPC (C#) | C# | ~10.400 QPS | 18 ms | Médio |
| Horse gRPC (Otimizado) | Delphi / FPC | 9.773 QPS | 20 ms | Muito Baixo (Estável) |
| gRPC-JS (Node.js) | JavaScript | ~3.800 QPS | 58 ms | Alto |
O Horse gRPC em Delphi entrega **2.5x mais vazão** e latência **3x menor** que o Node.js, emparelhando-se de igual para igual com o .NET da Microsoft (com apenas ~6% de diferença).
Conclusão
O ecossistema Delphi e Lazarus está mais vivo do que nunca. A implementação do provedor gRPC no Horse prova que compiladores nativos, quando aliados a uma engenharia de software caprichada em nível de ponteiros, alocação e concorrência, conseguem entregar performance no mesmo patamar de linguagens modernas como Rust e Go.
Se você quer dar o próximo passo e construir APIs e microsserviços de altíssima performance com Delphi e Lazarus, o código já está integrado na branch oficial do Horse. Comece hoje a usar gRPC!
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.