Aprenda os métodos práticos de Brendan Gregg (USE, RED, flame graphs) para investigar latência e gargalos em produção com dados, não achismos.

Brendan Gregg é uma das vozes mais influentes em desempenho de sistemas, especialmente no universo Linux. Ele escreveu livros amplamente usados, criou ferramentas práticas e — mais importante — compartilhou métodos claros para investigar problemas reais em produção. Equipes adotam sua abordagem porque funciona sob pressão: quando a latência sobe e todo mundo quer respostas, você precisa de um jeito de ir de “talvez seja X” para “é definitivamente Y” com o mínimo de drama.
Uma metodologia de desempenho não é uma única ferramenta ou um comando esperto. É uma forma repetível de investigar: um checklist do que olhar primeiro, como interpretar o que aparece e como decidir o próximo passo.
Essa repetibilidade é o que reduz suposições. Em vez de depender de quem tem mais intuição (ou da opinião mais alta), você segue um processo consistente que:
Muitas investigações de latência dão errado nos primeiros cinco minutos. As pessoas pulam direto para correções: “adicione CPU”, “reinicie o serviço”, “aumente o cache”, “ajuste a GC”, “deve ser a rede”. Às vezes essas ações ajudam — frequentemente elas escondem o sinal, desperdiçam tempo ou introduzem novo risco.
Os métodos do Gregg empurram você a atrasar as “soluções” até responder perguntas mais simples: O que está saturado? O que está gerando erros? O que ficou mais lento — throughput, enfileiramento ou operações individuais?
Este guia ajuda a restringir o escopo, medir os sinais certos e confirmar o gargalo antes de otimizar. O objetivo é um fluxo de trabalho estruturado para investigar latência e questões de perfilagem em produção para que os resultados não dependam da sorte.
Latência é um sintoma: usuários esperam mais tempo pelo término de um trabalho. A causa geralmente está em outro lugar — contenção de CPU, esperas em disco ou rede, contenção de locks, coleta de lixo, enfileiramento ou atrasos em dependências remotas. Medir apenas a latência diz que a dor existe, não de onde ela se origina.
Esses três sinais são acoplados:
Antes de ajustar, capture os três no mesmo intervalo de tempo. Caso contrário, você pode “resolver” a latência derrubando trabalho ou fazendo falhar mais rápido.
A latência média esconde picos que os usuários lembram. Um serviço com média de 50 ms pode ter stalls frequentes de 2 s.
Monitore percentis:
Observe também a forma da latência: um p50 estável com p99 subindo frequentemente indica stalls intermitentes (por exemplo, contenção de locks, hiccups de I/O, pausas stop-the-world) em vez de uma lentidão geral.
Um orçamento de latência é um modelo simples de contabilidade: “Se a requisição precisa terminar em 300 ms, como esse tempo pode ser gasto?” Divida em buckets como:
Esse orçamento orienta a primeira tarefa de medição: identifique qual bucket cresceu durante o pico e investigue essa área em vez de ajustar às cegas.
O trabalho de latência saí do rumo quando o “problema” é descrito como o sistema está lento. Os métodos do Gregg começam antes: force a questão a uma pergunta específica e testável.
Anote duas frases antes de tocar em qualquer ferramenta:
Isso evita otimizar a camada errada — por exemplo, CPU do host — quando a dor está isolada a um endpoint ou a uma dependência downstream.
Escolha uma janela que bata com a queixa e inclua um período de comparação “bom”, se possível.
Defina explicitamente o escopo da investigação:
Ser preciso aqui torna os passos seguintes (USE, RED, perfilagem) mais rápidos porque você saberá quais dados devem mudar se sua hipótese estiver certa.
Anote deploys, mudanças de configuração, shifts de tráfego e eventos de infraestrutura — mas não assuma causalidade. Escreva-os como “Se X, então esperaríamos Y”, para que você possa confirmar ou rejeitar rapidamente.
Um pequeno log evita trabalho duplicado entre colegas e facilita handoffs.
Time | Question | Scope | Data checked | Result | Next step
Mesmo cinco linhas como essa podem transformar um incidente estressante em um processo repetível.
O Método USE (Utilization, Saturation, Errors) é o checklist rápido do Gregg para escanear os “quatro grandes” recursos — CPU, memória, disco (armazenamento) e rede — para que você pare de adivinhar e comece a estreitar o problema.
Em vez de olhar dezenas de dashboards, faça as mesmas três perguntas para cada recurso:
Aplicado de forma consistente, isso vira um inventário rápido de onde existe “pressão”.
Para CPU, utilização é % de CPU ocupado, saturação aparece como pressão na run-queue ou threads esperando para rodar, e erros podem incluir throttling (em containers) ou interrupts mal comportados.
Para memória, utilização é memória usada, saturação frequentemente aparece como paginação ou coleta de lixo frequente, e erros incluem falhas de alocação ou eventos OOM.
Para disco, utilização é tempo de dispositivo ocupado, saturação é profundidade de fila e tempo de espera de leitura/gravação, e erros são erros de I/O ou timeouts.
Para rede, utilização é throughput, saturação são drops/filas/latência, e erros são retransmissões, resets ou perda de pacotes.
Quando os usuários reportam lentidão, sinais de saturação costumam ser os mais reveladores: filas, tempo de espera e contenção tendem a correlacionar mais diretamente com latência do que utilização bruta.
Métricas em nível de serviço (como latência de requisição e taxa de erro) dizem o impacto. USE diz onde olhar a seguir identificando qual recurso está sob pressão.
Um loop prático é:
O Método RED mantém você ancorado na experiência do usuário antes de mergulhar em gráficos de host.
RED impede que você persiga métricas de sistema “interessantes” que não afetam os usuários. Força um ciclo mais apertado: qual endpoint está lento, para quais usuários e desde quando? Se a Duration sobe apenas em uma rota enquanto a CPU geral está estável, você já tem um ponto de partida mais afiado.
Um hábito útil: mantenha RED quebrado por serviço e principais endpoints (ou principais métodos RPC). Isso facilita distinguir uma degradação ampla de uma regressão localizada.
RED diz onde dói. USE ajuda a testar qual recurso é responsável.
Exemplos:
Mantenha o layout focado:
Se quiser um fluxo de incidente consistente, emparelhe esta seção com o inventário USE em /blog/use-method-overview para que você possa mover de “os usuários sentem” para “este recurso é a restrição” com menos tração.
Uma investigação de desempenho pode explodir em dezenas de gráficos e hipóteses em minutos. A mentalidade do Gregg é manter estreito: seu trabalho não é “coletar mais dados”, mas fazer a próxima pergunta que elimina incerteza o mais rápido possível.
A maioria dos problemas de latência é dominada por um único custo (ou um pequeno par): um lock quente, uma dependência lenta, um disco sobrecarregado, um padrão de pausa de GC. Priorizar significa caçar esse custo dominante primeiro, porque reduzir 5% em cinco lugares raramente muda a latência visível ao usuário.
Um teste prático: “O que poderia explicar a maior parte da mudança de latência que estamos vendo?” Se uma hipótese só explica uma fatia pequena, é uma pergunta de menor prioridade.
Use top-down quando estiver respondendo “Os usuários estão impactados?” Comece por endpoints (sinais estilo RED): latência, throughput, erros. Isso evita otimizar algo que não está no caminho crítico.
Use bottom-up quando o host estiver claramente doente (sintomas estilo USE): saturação de CPU, pressão de memória fora de controle, I/O elevado. Se um nó está no limite, você vai perder tempo olhando percentis de endpoint sem entender a restrição.
Quando um alerta dispara, escolha um ramo e mantenha-se nele até confirmar ou falsificar:
Limite-se a um pequeno conjunto inicial de sinais e aprofunde apenas quando algo se mover. Se precisar de um checklist para manter o foco, vincule seus passos a um runbook como /blog/performance-incident-workflow para que cada nova métrica tenha um propósito: responder a uma pergunta específica.
Perfilagem em produção pode parecer arriscada porque toca o sistema vivo — mas frequentemente é a via mais rápida para trocar debate por evidência. Logs e dashboards podem dizer que algo está lento. Perfilagem diz onde o tempo vai: quais funções estão quentes, quais threads esperam e quais caminhos de código dominam durante o incidente.
Perfilagem é uma ferramenta de “orçamento de tempo”. Em vez de debater teorias (“é o banco de dados” vs “é a GC”), você obtém evidência como “45% das amostras de CPU estavam em parsing de JSON” ou “a maioria das requisições está bloqueada em um mutex”. Isso restringe o próximo passo a uma ou duas correções concretas.
Cada uma responde a uma pergunta diferente. Latência alta com CPU baixa frequentemente aponta para off-CPU ou contenção de locks em vez de pontos quentes de CPU.
Muitas equipes começam on-demand e depois migram para sempre ligado quando confiam na segurança e veem issues recorrentes.
Perfilagem segura em produção é sobre controlar custo. Prefira amostragem (não trace cada evento), mantenha janelas de captura curtas (por exemplo, 10–30 segundos) e meça overhead em um canário primeiro. Se estiver em dúvida, comece com amostragem de baixa frequência e aumente só se o sinal estiver muito ruidoso.
Flame graphs visualizam onde o tempo amostrado foi durante uma janela de perfilagem. Cada “caixa” é uma função (ou frame de pilha), e cada pilha mostra como a execução chegou nessa função. Eles são excelentes para identificar padrões rapidamente — mas não dizem automaticamente “o bug está aqui”.
Um flame graph normalmente representa amostras on-CPU: tempo em que o programa realmente rodou em um core de CPU. Pode destacar caminhos de código que queimam CPU, parsing ineficiente, serialização excessiva ou hotspots que realmente consomem CPU.
Não mostra diretamente espera em disco, rede, atrasos do escalonador ou tempo bloqueado em um mutex (isso é off-CPU e precisa de outro tipo de perfilagem). Também não prova causalidade para latência percebida pelo usuário a menos que você conecte à uma questão bem delimitada.
A caixa mais larga é tentadora para culpar, mas pergunte: é um hotspot que você pode mudar ou apenas “tempo gasto em malloc, GC ou logging” porque o problema real está mais acima na cadeia? Também fique atento a contexto faltante (JIT, inlining, símbolos) que pode fazer uma caixa parecer culpada quando ela é só mensageira.
Trate um flame graph como resposta a uma pergunta delimitada: qual endpoint, qual janela de tempo, quais hosts e o que mudou. Compare flame graphs “antes vs depois” (ou “saudável vs degradado”) para o mesmo caminho de requisição para evitar ruído de perfilagem.
Quando a latência dispara, muitas equipes olham para %CPU primeiro. Isso é compreensível — mas frequentemente aponta na direção errada. Um serviço pode estar “com só 20% de CPU” e ainda assim ser dolorosamente lento se suas threads passam a maior parte do tempo não rodando.
%CPU responde “quão ocupado está o processador?” Não responde “onde foi o tempo da minha requisição?” Requisições podem travar enquanto threads estão esperando, bloqueadas ou estacionadas pelo escalonador.
Uma ideia chave: o tempo de relógio de uma requisição inclui tanto trabalho on-CPU quanto espera off-CPU.
Tempo off-CPU tipicamente esconde dependências e contenção:
Alguns sinais costumam correlacionar com gargalos off-CPU:
Esses sintomas dizem “estamos esperando”, mas não no que estamos esperando.
A perfilagem off-CPU atribui tempo ao motivo pelo qual você não estava rodando: bloqueado em syscalls, esperando locks, dormindo ou desescalonado. Isso é poderoso para trabalho de latência porque transforma lentidões vagas em categorias acionáveis: “bloqueado no mutex X”, “esperando read() do disco” ou “preso em connect() para um upstream”. Uma vez que você consegue nomear a espera, pode medi-la, confirmá-la e corrigi-la.
O trabalho de desempenho costuma falhar no mesmo momento: alguém vê uma métrica suspeita, declara “isso é o problema” e começa a ajustar. Os métodos do Gregg empurram você a desacelerar e provar o que está limitando o sistema antes de mudar qualquer coisa.
Um gargalo é o recurso ou componente que no momento limita throughput ou dirige a latência. Se você aliviá-lo, os usuários veem melhoria.
Um hotspot é onde o tempo é gasto (por exemplo, uma função que aparece frequentemente em um perfil). Hotspots podem ser gargalos reais — ou apenas trabalho ocupado que não afeta o caminho lento.
Ruído é tudo que parece significativo mas não é: jobs em background, picos isolados, artefatos de amostragem, efeitos de cache ou “top talkers” que não se correlacionam com o problema visível ao usuário.
Comece capturando um snapshot limpo de antes: o sintoma voltado ao usuário (latência ou taxa de erro) e os sinais candidatos principais (saturação de CPU, profundidade de fila, I/O de disco, contenção de locks etc.). Então aplique uma mudança controlada que deva afetar apenas a causa suspeita.
Exemplos de testes causais:
Correlação é uma pista, não um veredito. Se “a CPU sobe quando a latência sobe”, verifique mudando a disponibilidade de CPU ou reduzindo trabalho de CPU e observando se a latência acompanha.
Anote: o que foi medido, a mudança exata feita, os resultados antes/depois e a melhoria observada. Isso transforma uma vitória pontual em um playbook reutilizável para o próximo incidente — e evita que “intuição” reescreva a história depois.
Incidentes de desempenho parecem urgentes, e é exatamente quando suposições aparecem. Um fluxo leve e repetível ajuda a ir de “algo está lento” para “sabemos o que mudou” sem thrashing.
Detectar: alerte na latência e taxa de erro visíveis aos usuários, não só na CPU. Chame quando p95/p99 cruzarem um limiar por uma janela sustentada.
Triagem: responda imediatamente três perguntas: o que está lento, quando começou e quem está afetado? Se você não consegue nomear o escopo (serviço, endpoint, região, coorte), não está pronto para otimizar.
Medir: colete evidências que estreitem o gargalo. Prefira capturas com limite de tempo (por exemplo, 60–180 segundos) para poder comparar “ruim” vs “bom”.
Consertar: mude uma coisa por vez e então meça os mesmos sinais para confirmar a melhoria e descartar placebo.
Mantenha um dashboard compartilhado que todos usam durante incidentes. Torne-o entediante e consistente:
O objetivo não é graficar tudo; é encurtar o tempo-para-primeiro-fato.
Instrumente os endpoints que importam (checkout, login, busca), não todos os endpoints. Para cada um, concorde em: p95 esperado, taxa máx de erro e dependência chave (BD, cache, terceiro).
Antes do próximo outage, concorde um kit de captura:
Documente num runbook curto (por exemplo, /runbooks/latency), incluindo quem pode rodar capturas e onde os artefatos são armazenados.
A metodologia do Gregg é fundamentalmente sobre mudança controlada e verificação rápida. Se sua equipe constrói serviços usando o Koder.ai (uma plataforma orientada por chat para gerar e iterar apps web, backend e mobile), duas funcionalidades se alinham bem a essa mentalidade:
Mesmo que você não esteja gerando novo código durante um incidente, esses hábitos — diffs pequenos, resultados mensuráveis e rápida reversibilidade — são os mesmos hábitos que o Gregg promove.
São 10:15 e seu dashboard mostra p99 da API subindo de ~120ms para ~900ms durante o pico. A taxa de erro está estável, mas clientes relatam requisições “lentas”.
Comece centrado no serviço: Rate, Errors, Duration.
Fatie Duration por endpoint e veja uma rota dominando o p99: POST /checkout. A Rate subiu 2×, erros normais, mas a Duration dispara especificamente quando a concorrência aumenta. Isso aponta para enfileiramento ou contenção, não uma falha completa.
Em seguida, verifique se a latência é tempo de computação ou de espera: compare “handler time” da aplicação com o tempo total da requisição (ou spans upstream vs downstream se tiver tracing). O handler time é baixo, o tempo total é alto — requisições estão esperando.
Faça o inventário dos gargalos prováveis: Utilização, Saturação, Erros para CPU, memória, disco e rede.
A utilização de CPU está só em ~35%, mas a run queue e as trocas de contexto sobem. Disco e rede parecem estáveis. Esse desencontro (CPU baixo, espera alta) é uma dica clássica: threads não estão queimando CPU — estão bloqueadas.
Você captura um perfil off-CPU durante o pico e encontra muito tempo em um mutex ao redor de um cache compartilhado de “validação de promoção”.
Você substitui o lock global por um lock por chave (ou uma via de leitura sem lock), faz o deploy e observa o p99 voltar ao baseline enquanto a Rate permanece alta.
Checklist pós-incidente: