DevGuideTK

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

LinguagemCPUMemóriaObservação
Nodenode --cpu-prof, --prof; painel de desempenho do Chrome com --inspect--heap-prof, instantâneos do heap no ChromeFunções embutidas pelo V8 aparecem no lugar de quem as chamou
PythoncProfile (instrumentação), py-spy (amostragem, inclusive num processo rodando)tracemalloc, memraycProfile e tracemalloc pesam bastante: no teste, o tracemalloc deixou o programa mais de quatro vezes mais lento
Gopprof (runtime/pprof ou net/http/pprof)O mesmo pprof, com perfis de heap e de alocaçãoEmbutido na linguagem; o mais simples de usar em produção
JavaJDK Flight Recorder (JFR), async-profilerJFR, instantâneos do heap com Eclipse MATA JFR foi feita para rodar em produção com peso baixo
C#dotnet-trace, Visual Studio, PerfViewdotnet-gcdump, dotnet-countersNa versão 10 do dotnet-trace, os perfis mudaram de nome; o padrão já inclui a amostragem de CPU
Qualquer processoperf do Linux, eBPF (Parca, Pyroscope)—Sem mexer no código; precisa de símbolos para mostrar nomes

Onde medir

AmbienteVantagensCuidados
Máquina do desenvolvedorRápido, sem riscoOs dados e a carga não são os de produção; o gargalo pode ser outro
Ambiente de testes com carga simuladaRepetível; dá para comparar antes e depoisPrecisa de dados e de carga realistas, como mostra o tópico de testes de carga
Produção, sob demandaO comportamento realUse 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 passadaPeso 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

SintomaPerfilO que procurar
CPU alta, requisições lentasCPU por amostragemA barra mais larga no gráfico de chama, e quem a chama
Requisições lentas com CPU baixaTempo de parede, ou rastreamentoEspera: banco, rede, travas; um perfil de CPU não mostra o tempo parado
Memória crescendo sem pararHeap em dois momentos, comparadosO que cresceu entre os dois instantâneos
Pausas do coletor de lixoAlocaçõesQuem aloca mais por segundo
Travas e disputa entre threadsPerfil 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

  1. Reproduza o problema com dados e carga realistas; um perfil com 10 registros não mostra um O(n²).
  2. Meça com o profiler adequado ao sintoma.
  3. Leia o acumulado, e não só o próprio: suba pela pilha até o código da aplicação.
  4. Corrija o maior bloco, e só ele.
  5. Meça de novo, sem o profiler, para confirmar o ganho com números reais.
  6. 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

  1. Conheça o profiler da sua linguagem antes de precisar dele.
  2. Amostragem para produção, instrumentação para detalhes locais.
  3. CPU para o que é lento com CPU alta; rastreamento para o que espera.
  4. Leia o tempo acumulado, e use gráficos de chama.
  5. Meça com dados realistas, corrija o maior bloco e meça de novo, sem o profiler.
  6. 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.