Skip to content
mobius1qwe edited this page Nov 4, 2026 · 5 revisions

Home > Desempenho

Desempenho

Delphi e Lazarus · Nível: intermediário

Em uma frase: os ajustes que mais pesam quando o servidor recebe muitos pedidos ou corpos grandes.

No servidor

Ajuste Onde Quando
Atualize o RAL — o Indy e o fpHTTP tinham uma espera fixa de ~40 ms por pedido, corrigida na 1.1; a 1.2 e a 2.0 🚧 cortaram cópias de memória e travas por pedido
Modo do mORMot2 1.2 Mode := smAsync muitas conexões abertas (ver Qual motor)
Limite de conexões MaxConnections (Indy; Sagui, fpHTTP e mORMot2 smAsync/smHttpSys na 1.2) proteger a máquina; passou do limite, a conexão nova é recusada
Keep-alive no mORMot2 1.2 MaxKeepAliveConnections (smThreads) acima do limite, as conexões deixam de ser mantidas: tudo funciona, mais devagar
Fila de pedidos 2.0 🚧 TRALConcurrencyPlugin picos: limita quantos pedidos rodam ao mesmo tempo; o resto espera ou recebe 503
Pool do banco TRALDBModule.PoolOptions toda API com banco (DBWare)
Compressão TRALCompressPlugin (2.0 🚧) / CompressType respostas de texto grandes; imagem e zip não são recomprimidos
Corpo grande em disco 2.0 🚧 TRALLimitsPlugin.SpoolAbove (bytes) uploads de centenas de MB; ver Corpo sem cópias
Responder sem copiar 2.0 🚧 Answer(status, stream, tipo, True) ou AResponse.BodyStream arquivos e relatórios gerados na rota

TRALConcurrencyPlugin 2.0 🚧

uses RALConcurrency;

RALConcurrencyPlugin1.Server := Servidor;
RALConcurrencyPlugin1.MaxConcurrent := 0;     // 0 = 2 × processadores
RALConcurrencyPlugin1.MaxQueueWait := 30000;  // ms na fila; 0 = esperar sempre
RALConcurrencyPlugin1.RetryAfter := 1;        // segundos sugeridos ao cliente no 503

O pedido recusado antes (senha, IP, tamanho) nem entra na fila.

Servidor no Lazarus (FPC) 2.0 🚧

O gerenciador de memória do FPC 3.2 guarda, por thread, só 4 blocos de memória vazios para reaproveitar; o resto ele devolve ao sistema e pede de novo no pedido seguinte. Um pedido do RAL usa mais tamanhos de bloco que isso, e sem ajuste um servidor em smThreads (uma thread por conexão) fica 5 a 15 vezes mais lento - e um cabeçalho um byte maior pode ser o que passa do limite.

Ao ativar, o servidor sobe esse limite (MaxKeptOSChunks do FPC) para RALHeapKeptChunks (16). Ele nunca é baixado, e cada thread guarda no máximo esses 16 blocos vazios (de 32 KB a 256 KB cada).

uses RALServer;

RALHeapKeptChunks := 32;  // antes de ativar; 0 = não mexer no heap do FPC

Para o máximo, troque o gerenciador de memória do programa - ele precisa ser a primeira unidade do uses do .lpr, antes até do cthreads:

Gerenciador Como
cmem (o malloc da libc) uses cmem, cthreads, ...
o do mORMot2 (x86_64) uses cthreads, mormot.core.fpcx64mm, ... e defina FPC_X64MM (FPCMM_SERVER para serviços)

Com qualquer um dos dois, RALHeapKeptChunks não faz diferença.

No cliente

Ajuste Onde Quando
Reaproveitar a conexão PoolConnection.Enabled (ligado na 1.2) e KeepAlive sempre
Dividir a conexão entre clientes ShareConnection (ligado na 1.2; NetHTTP, OkHttp, QUIC) vários datasets/clientes para o mesmo servidor
HTTP/2 HTTPVersion := rhv2 muitos pedidos simultâneos ao mesmo servidor (HTTP/2)
Não travar a tela ebMultiThread chamadas a partir de botões (O cliente)

Programa de 32 bits

Um processo de 32 bits tem ~2 GB de endereços. Corpos de centenas de MB em Win32: só com SpoolAbove (2.0 🚧), ou compile em 64 bits.

Medir

Antes de mudar, meça: a mesma rota, a mesma máquina, várias rodadas. Ferramentas comuns: JMeter, wrk, hey, ab. O projeto mantém uma bateria própria (RALOrquestrador) usada nos testes de carga.

Veja também

Começar

Servidor

MQTT 🚧

Cliente

Motores

Avançado

Ajuda

🚧 = em desenvolvimento, pode mudar

Clone this wiki locally