Como usar perf para profiling de CPU em processos Linux

1. Introdução ao perf e preparação do ambiente

O perf é uma ferramenta de profiling nativa do kernel Linux, parte do subsistema perf_events. Diferente de soluções externas como gprof ou Valgrind, o perf opera com sobrecarga mínima, utilizando contadores de hardware da CPU para coletar amostras precisas de execução. Ele é ideal para identificar gargalos de desempenho, analisar uso de cache e medir eficiência de instruções.

Instalação e verificação de permissões

Em distribuições baseadas em Debian/Ubuntu, instale com:

sudo apt-get install linux-tools-common linux-tools-generic linux-tools-$(uname -r)

No CentOS/RHEL:

sudo yum install perf

Verifique as permissões do sistema:

cat /proc/sys/kernel/perf_event_paranoid
cat /proc/sys/kernel/kptr_restrict

Ajuste se necessário (para uso sem sudo):

sudo sysctl -w kernel.perf_event_paranoid=1
sudo sysctl -w kernel.kptr_restrict=0

Estrutura básica do comando

Liste eventos disponíveis com perf list:

perf list

Teste a ferramenta com perf stat em um comando simples:

perf stat ls

Isso exibe contagens básicas como ciclos, instruções e cache misses.

2. Coleta de estatísticas gerais com perf stat

O perf stat executa um comando e coleta contadores de hardware. Exemplo com eventos específicos:

perf stat -e cycles,instructions,cache-misses,branch-misses ./meu_programa

Interpretação de métricas

A saída típica:

Performance counter stats for './meu_programa':

       1.234.567.890      cycles
       2.345.678.901      instructions
              12.345      cache-misses
              45.678      branch-misses

       0,987654321 seconds time elapsed

O IPC (instruções por ciclo) é calculado como instructions / cycles. Valores baixos indicam stalls de memória ou dependências de dados. Taxa de cache miss alta sugere má localidade de dados.

Exemplo prático: comparando implementações

Compare duas funções de ordenação:

perf stat -e cycles,instructions,cache-misses ./quick_sort
perf stat -e cycles,instructions,cache-misses ./bubble_sort

A saída revelará que o quick_sort tem IPC mais alto e menos cache misses, justificando sua eficiência.

3. Amostragem de eventos com perf record e perf report

Para profiling mais detalhado, use perf record com amostragem:

perf record -F 99 -g -- ./meu_programa
  • -F 99: frequência de amostragem de 99 Hz (evita sincronia com clocks de sistema)
  • -g: captura call graphs (pilha de chamadas)

Gere o relatório:

perf report

O perf report abre uma interface TUI. Use as setas para navegar, Enter para expandir funções. A coluna Overhead mostra o percentual de amostras em cada símbolo. Ordenação padrão é por overhead; pressione S para ordenar por símbolo.

4. Análise de call graphs e hotspots

No relatório, funções com maior overhead são os hotspots. Para inspecionar uma função específica:

perf annotate -s nome_da_funcao

Isso mostra o assembly da função com contagens de amostras por instrução, permitindo identificar linhas de código problemáticas.

Reduzindo ruído

Filtre por PID de um processo específico:

perf record -F 99 -g -p 12345

Ou por CPU:

perf record -F 99 -g -C 0,1 -- ./meu_programa

Para eventos específicos (ex.: cache misses):

perf record -e cache-misses -F 99 -g -- ./meu_programa

5. Profiling de processos em execução e aplicações reais

Anexe perf a um processo já rodando:

perf record -F 99 -g -p $(pgrep -x mysqld)

Colete por tempo limitado:

perf record -F 99 -g -p $(pgrep -x nginx) --sleep 10

Exemplo prático: profiling de servidor web

Suponha um servidor Nginx em produção. Anexe perf por 30 segundos:

perf record -F 99 -g -p $(pgrep -x nginx) --sleep 30

Analise o relatório:

perf report

Hotspots comuns incluem funções de manipulação de strings, parsing HTTP ou syscalls de rede. O perf revela onde o CPU gasta mais tempo, orientando otimizações.

6. Visualização de dados com perf script e ferramentas externas

Exporte dados para análise textual:

perf script > dados_perf.txt

Geração de Flame Graphs

Instale os scripts auxiliares:

git clone https://github.com/brendangregg/FlameGraph
cd FlameGraph

Converta os dados:

perf script | ./stackcollapse-perf.pl > out.folded
./flamegraph.pl out.folded > flame.svg

Abra o SVG no navegador para visualizar chamas de chamadas.

Uso de perf timechart

Visualize atividade da CPU ao longo do tempo:

perf timechart record ./meu_programa
perf timechart

Isso gera um SVG com barras de execução por thread e estado (running, sleeping, etc.).

7. Boas práticas, limitações e solução de problemas comuns

Impacto no desempenho

O overhead do perf é geralmente baixo (1-5% com amostragem a 99 Hz). Evite frequências muito altas (ex.: 1000 Hz) em sistemas de produção. Use -p para limitar a um processo específico.

Limitações

  • Eventos de hardware podem não estar disponíveis em máquinas virtuais ou contêineres sem privilégios.
  • perf não rastreia I/O de disco ou rede diretamente (use perf trace para syscalls).
  • Amostragem é estatística; pode perder eventos raros.

Erros frequentes

  • perf_event_paranoid muito alto: ajuste para 1 ou use sudo.
  • kptr_restrict impede resolução de símbolos do kernel: ajuste para 0.
  • Eventos não disponíveis: verifique com perf list e use perf stat -e cpu-cycles como fallback.

Solução de problemas

Se perf report mostrar [unknown], instale símbolos de depuração:

sudo apt-get install linux-image-$(uname -r)-dbg

Para processos otimizados (compilados com -O2), use -fno-omit-frame-pointer para call graphs completos.

Referências