Profiling
Como medir onde o tempo e a memória são gastos antes de otimizar.
As decisões de profiling são quatro: qual ferramenta, onde medir, o que medir e como transformar o resultado em correção.
As ferramentas de cada linguagem
| Linguagem | CPU | Memória | Observação |
|---|---|---|---|
| Node | node --cpu-prof, --prof; painel de desempenho do Chrome com --inspect | --heap-prof, instantâneos do heap no Chrome | Funções embutidas pelo V8 aparecem no lugar de quem as chamou |
| Python | cProfile (instrumentação), py-spy (amostragem, inclusive num processo rodando) | tracemalloc, memray | cProfile e tracemalloc pesam bastante: no teste, o tracemalloc deixou o programa mais de quatro vezes mais lento |
| Go | pprof (runtime/pprof ou net/http/pprof) | O mesmo pprof, com perfis de heap e de alocação | Embutido na linguagem; o mais simples de usar em produção |
| Java | JDK Flight Recorder (JFR), async-profiler | JFR, instantâneos do heap com Eclipse MAT | A JFR foi feita para rodar em produção com peso baixo |
| C# | dotnet-trace, Visual Studio, PerfView | dotnet-gcdump, dotnet-counters | Na versão 10 do dotnet-trace, os perfis mudaram de nome; o padrão já inclui a amostragem de CPU |
| Qualquer processo | perf do Linux, eBPF (Parca, Pyroscope) | — | Sem mexer no código; precisa de símbolos para mostrar nomes |
Onde medir
| Ambiente | Vantagens | Cuidados |
|---|---|---|
| Máquina do desenvolvedor | Rápido, sem risco | Os dados e a carga não são os de produção; o gargalo pode ser outro |
| Ambiente de testes com carga simulada | Repetível; dá para comparar antes e depois | Precisa de dados e de carga realistas, como mostra o tópico de testes de carga |
| Produção, sob demanda | O comportamento real | Use profilers por amostragem, por tempo limitado, numa instância |
| Produção, contínuo (continuous profiling) | Histórico: dá para comparar o perfil de hoje com o da semana passada | Peso pequeno e constante; Pyroscope, Parca, Datadog, Grafana |
O profiling contínuo responde a uma pergunta que nenhum outro método responde: "o que mudou desde o deploy de ontem?". Com o perfil guardado ao longo do tempo, a função que passou a pesar aparece na comparação.
O que medir
| Sintoma | Perfil | O que procurar |
|---|---|---|
| CPU alta, requisições lentas | CPU por amostragem | A barra mais larga no gráfico de chama, e quem a chama |
| Requisições lentas com CPU baixa | Tempo de parede, ou rastreamento | Espera: banco, rede, travas; um perfil de CPU não mostra o tempo parado |
| Memória crescendo sem parar | Heap em dois momentos, comparados | O que cresceu entre os dois instantâneos |
| Pausas do coletor de lixo | Alocações | Quem aloca mais por segundo |
| Travas e disputa entre threads | Perfil de bloqueio (pprof block e mutex, JFR) | Onde as threads esperam umas pelas outras |
A segunda linha merece destaque: se a requisição demora porque espera o banco, o perfil de CPU mostra um processo quase parado, e o gargalo não aparece. Para tempo de espera, o caminho é o rastreamento distribuído, como mostra o tópico de rastreamento, e o plano de execução da consulta, como mostra o tópico de plano de execução.
Do perfil à correção
- Reproduza o problema com dados e carga realistas; um perfil com 10 registros não mostra um O(n²).
- Meça com o profiler adequado ao sintoma.
- Leia o acumulado, e não só o próprio: suba pela pilha até o código da aplicação.
- Corrija o maior bloco, e só ele.
- Meça de novo, sem o profiler, para confirmar o ganho com números reais.
- Proteja com um teste de desempenho ou um benchmark, para o gargalo não voltar.
Os erros que mais aparecem num perfil de aplicação são poucos e repetidos: buscas lineares dentro de laços (o caso do teste), consultas ao banco dentro de laços (o N+1 do tópico de ORMs), serialização repetida, expressões regulares compiladas a cada chamada, e cópias desnecessárias de coleções grandes.
Resumo da decisão
- Conheça o profiler da sua linguagem antes de precisar dele.
- Amostragem para produção, instrumentação para detalhes locais.
- CPU para o que é lento com CPU alta; rastreamento para o que espera.
- Leia o tempo acumulado, e use gráficos de chama.
- Meça com dados realistas, corrija o maior bloco e meça de novo, sem o profiler.
- Profiling contínuo quando o sistema já tem observabilidade madura.
O próximo nível mostra o relatório lento e o corrigido nas cinco linguagens, com os comandos de profiling de cada uma.
Prompts para aprofundar
Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.
Escolher a ferramenta de profiling
Quero saber como fazer profiling da minha aplicação. Pergunte qual linguagem, framework e ambiente eu uso (local, containers, Kubernetes, serviço gerenciado) e qual é o sintoma. Recomende a ferramenta para o sintoma, explique como coletar o perfil no meu ambiente, inclusive em produção, e como ler o resultado. No final, diga se faz sentido profiling contínuo para o meu caso.
Investigar uma lentidão em produção
Uma parte da minha aplicação ficou lenta em produção. Pergunte qual linguagem eu uso, o que ficou lento, desde quando, o que as métricas mostram (CPU, memória, latência) e o que mudou recentemente. Me guie: decidir se o problema é CPU, espera ou memória; escolher a ferramenta; coletar o perfil com segurança em produção; ler o resultado; e confirmar a correção.
Montar profiling contínuo
Quero ter profiling contínuo em produção. Pergunte quais linguagens e onde os serviços rodam, e que ferramentas de observabilidade já existem. Compare Pyroscope, Parca, Datadog e as opções da minha nuvem quanto a peso, linguagens suportadas, custo e integração. Monte comigo a configuração da opção escolhida e um roteiro para comparar o perfil antes e depois de um deploy.