Aplicação lenta no servidor: CPU steal, overselling e gargalos

Uma aplicação lenta tem um gargalo mensurável: CPU, memória, disco, rede ou código. Meça cada um antes de trocar de plano, porque mais recursos só ajudam quando o recurso é o limite.

Atualizado em 6 min de leitura

Objetivos de aprendizado

Depois de ler este artigo, você vai conseguir:

  • Reconhecer CPU steal, throttling e overselling pelos números
  • Diagnosticar memória, disco, rede e event loop com comandos reais
  • Decidir se o certo é otimizar o código ou mudar de servidor
Nesta página

"O servidor está lento" não é um diagnóstico, é um sintoma. Por trás dele há um recurso saturado (CPU, memória, disco, rede) ou um limite imposto de fora (CPU compartilhada com vizinhos, quota do container). E às vezes não é o servidor: é uma consulta sem índice ou um laço bloqueando o processo.

Trocar de plano sem medir é o erro mais caro nesse cenário. A investigação abaixo vai do mais barato ao mais difícil, com os comandos que separam cada causa.

Aplicação lentameça antes de mudar de planoCPU alta?top: us, sysimCódigo ou limite de CPUcpu.stat: nr_throttlednãoSteal alto?vmstat: stsimVizinho barulhentomude para CPU dedicadanãoUsando swap?vmstat: si/sosimFalta de memóriamemory.events: oom_killnãoiowait alto?vmstat: wasimDisco saturadoiostat -x 1nãoTudo baixo: banco, API ou redelog de consultas lentas e timeouts
Meça um recurso por vez, do mais barato ao mais difícil; só troque de plano quando o número apontar o limite.

Como saber se é CPU, memória, disco ou rede?#

Comece pelo que a máquina diz de si mesma. Em um servidor Linux, três comandos respondem quase tudo:

bash
top            # linha "%Cpu(s)": us, sy, wa (I/O) e st (steal)
vmstat 1 5     # r (fila de CPU), si/so (swap), wa, st, uma linha por segundo
free -m        # memória disponível e uso de swap

Leia assim:

  • us/sy altos e fila r maior que o número de núcleos: CPU saturada.
  • si/so diferentes de zero: o sistema está usando swap, ou seja, falta memória.
  • wa alto: processos esperando disco.
  • st alto: CPU roubada pelo hipervisor (próxima seção).
  • Tudo baixo e a aplicação lenta: o tempo está sendo gasto esperando algo externo (banco, API, rede) ou dentro de código que não usa muita CPU.

O que é CPU steal e o que é overselling?#

Em uma VPS, o seu "servidor" é uma máquina virtual, e várias VMs dividem os mesmos núcleos físicos. O campo steal do Linux é, segundo a página proc_stat do manual, o tempo gasto em outros sistemas operacionais quando rodando em ambiente virtualizado: a sua VM tinha trabalho a fazer e o hipervisor deu o núcleo a outra.

Overselling (ou overcommit) é quando o provedor aloca mais vCPUs aos clientes do que há núcleos físicos, apostando que nem todos usam ao mesmo tempo. É uma prática comum em planos baratos, mas quando os vizinhos usam CPU ao mesmo tempo, o seu steal sobe. Alguns tipos de instância também são explicitamente "burstable": a AWS descreve as instâncias T como uma CPU de base com capacidade de picos acima dela, e não como CPU cheia o tempo todo.

Como diagnosticar:

  1. Rode vmstat 1 60 durante a lentidão e olhe a coluna st.
  2. Se st fica alto de forma repetida enquanto a sua CPU de usuário (us) é baixa, o gargalo não é o seu código.
  3. Repita em horários diferentes. Steal que some de madrugada e volta à noite indica vizinho barulhento.

A correção não está na sua aplicação: é mudar de tipo de instância (CPU dedicada), de região ou de provedor. Antes, abra um chamado com os números, que é a prova que o suporte pede.

O que é throttling de CPU em container?#

Em containers existe outra causa que parece steal mas não é. O container recebe uma quota de CPU: no cgroup v2, o arquivo cpu.max define quanto tempo de CPU o grupo pode usar por período (o padrão é max 100000, sem limite). Ao passar da quota, o kernel pausa os processos até o próximo período, e isso aparece como latência em picos.

Dentro do container, confira:

bash
cat /sys/fs/cgroup/cpu.max    # ex.: "50000 100000" = meio núcleo
cat /sys/fs/cgroup/cpu.stat   # nr_throttled e throttled_usec crescendo = throttling

Se nr_throttled cresce enquanto a aplicação está lenta, o limite de CPU do container é o gargalo. Aumente o limite ou reduza o trabalho por requisição. Ao contrário do steal, aqui a solução está nas suas mãos.

A aplicação está sem memória?#

A falta de memória costuma aparecer de duas formas. A primeira é lentidão por swap: o sistema move páginas para o disco e tudo desacelera, e o vmstat mostra si/so ativos. A segunda é o processo morrer: o kernel encerra processos que passam do limite do container e o contador oom_kill em memory.events sobe.

bash
cat /sys/fs/cgroup/memory.events   # oom_kill > 0: algo foi encerrado por falta de memória

Um sinal clássico é a aplicação ficar mais lenta com o passar das horas e voltar ao normal depois de um reinício: isso é vazamento de memória ou cache sem limite. Veja como medir o pico e dimensionar com folga em Quanta RAM e CPU minha aplicação precisa?.

E se a CPU e a memória estão folgadas?#

Então o tempo está sendo gasto esperando. Os suspeitos, em ordem de frequência:

  1. Banco de dados: consulta sem índice, N+1 (uma consulta por item de uma lista) ou conexão aberta a cada requisição. Ative o log de consultas lentas do seu banco e meça o tempo de cada uma.
  2. API externa: uma chamada lenta de terceiro dentro do caminho da requisição. Coloque timeout e, quando possível, tire a chamada do caminho crítico.
  3. Disco: wa alto no vmstat, ou iostat -x 1 (pacote sysstat) com o disco saturado. Logs em excesso, arquivos temporários grandes e bancos em disco lento são os culpados típicos. A página do manual avisa que o valor de iowait é pouco confiável, então use-o como pista, não como prova.
  4. Distância: latência de rede entre aplicação e banco, ou entre servidor e usuário. Aplicação e banco devem ficar no mesmo datacenter, e o conteúdo estático ganha muito com uma CDN.

Como achar o gargalo dentro do código?#

Em Node.js, o sintoma típico é o event loop bloqueado: um laço pesado ou uma operação síncrona impede o processo de atender qualquer outra requisição. O módulo perf_hooks mede esse atraso diretamente:

js
// event-loop.js: imprime o atraso do event loop a cada 5 segundos
const { monitorEventLoopDelay } = require("node:perf_hooks");

const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();

setInterval(() => {
  const ms = (ns) => (ns / 1e6).toFixed(1);
  console.log(
    `event loop: média=${ms(h.mean)} ms p99=${ms(h.percentile(99))} ms máx=${ms(h.max)} ms`,
  );
  h.reset();
}, 5000);

Os valores vêm em nanossegundos, por isso a divisão por 1e6. Com a CPU livre, um p99 de centenas de milissegundos indica código bloqueando o loop. Em Python, o equivalente é um profiler como o cProfile rodando por alguns minutos sob carga. O padrão é o mesmo: meça onde o tempo vai antes de alterar qualquer linha.

Registre também o tempo de cada requisição nos logs. Com a duração e a rota em cada linha, o gargalo costuma aparecer sozinho, e ler os logs da aplicação é o passo seguinte quando os números sozinhos não explicam.

Qual a ordem certa para investigar?#

  1. Confirme o sintoma com número: tempo de resposta por rota, não "parece lento".
  2. top/vmstat: CPU, steal, swap, iowait.
  3. Cgroup (cpu.stat, memory.events) se estiver em container.
  4. Banco e APIs externas: consultas lentas e timeouts.
  5. Profiler no código.
  6. Só então mude de plano ou de servidor, e meça de novo para confirmar que melhorou.

Se o steal é a causa, a escolha entre VPS e plataforma muda: veja VPS, cloud ou plataforma de hospedagem para comparar o que cada modelo isola.

Como fazer isso na Square Cloud#

Na Square Cloud, as aplicações rodam em containers isolados, sempre ligados, sem cold start nem modo de suspensão, num datacenter Tier 3 em Nova York com processadores Intel Dual Xeon de 3 GHz ou mais e armazenamento NVMe. Você acompanha os logs em tempo real no painel, na CLI, no VS Code e no app de celular, e as métricas de CPU, RAM e rede são registradas a cada 5 minutos e guardadas por 24 horas.

Se a falta de memória for a causa, você muda a RAM de cada aplicação nas configurações ou pela API. A RAM do plano é um pool compartilhado entre as suas aplicações, com mínimo de 256 MB por aplicação de fundo e 512 MB por aplicação web. O vCPU do plano é o teto por ambiente, calculado a partir da RAM alocada.

A hospedagem de bancos (a partir do Standard) fica no mesmo datacenter das aplicações, com cerca de 1 ms de latência média, o que tira a distância entre aplicação e banco da lista de suspeitos. Nos planos Pro e Enterprise, o analytics mostra a latência em p50, p95 e p99, além dos logs HTTP, para você achar as rotas lentas.

Não há autoscaling: você decide quando aumentar a RAM ou distribuir a carga com load balancing, colocando o mesmo domínio personalizado em várias aplicações (a partir do plano Standard). Veja os recursos de logs, métricas e escala.

Deploy

Envie pelo GitHub, pela CLI ou em ZIP e publique em segundos

Saiba mais

Perguntas frequentes

O que é CPU steal?

É o tempo em que a sua máquina virtual queria usar a CPU, mas o hipervisor a entregou a outra máquina virtual. Aparece como st no top e no vmstat e só existe em ambiente virtualizado.

Como saber se meu servidor sofre overselling de CPU?

Com a aplicação lenta e o seu uso de CPU baixo, olhe o steal. Valores altos e repetidos indicam que os núcleos físicos estão disputados por vizinhos. Meça em horários diferentes, porque a disputa varia ao longo do dia.

Mais RAM deixa a aplicação mais rápida?

Só se a falta de memória for o problema, por exemplo com swap ativo ou processos encerrados por falta de memória. Com RAM sobrando, contratar mais não muda a velocidade.

A aplicação é lenta só na primeira requisição. Por quê?

Costuma ser inicialização preguiçosa (conexão com banco, caches vazios) ou um processo que foi encerrado e precisa subir de novo. Mantenha o processo ligado e aqueça as conexões no início.

Próximo artigoUptime e SLA de 99,9%: o que significam na práticaUptime de 99,9% permite cerca de 43 minutos fora do ar por mês. Veja a conta, a diferença entre uptime, SLO e SLA e o que o SLA de fato garante.