Introdução: por que é importante perfilar código C++?
\nC++ é uma das linguagens de programação mais rápidas, mas mesmo nela é possível escrever código lento. Frequentemente, desenvolvedores gastam horas otimizando partes erradas do programa, guiados pela intuição. O perfilamento é uma abordagem científica para a otimização: você mede onde o programa gasta mais tempo e melhora esses pontos de forma direcionada.
\nPara programadores C++ iniciantes, o perfilamento pode parecer complexo, mas na verdade as ferramentas básicas são aprendidas em uma noite. Neste artigo, vamos explorar três ferramentas populares: gprof, perf e Valgrind, e aprender a interpretar seus resultados.
O que é perfilamento e quais são os métodos existentes?
\nPerfilamento é a coleta de dados sobre o funcionamento de um programa durante sua execução. Existem duas abordagens principais:
\n- \n
- Perfilamento por instrumentação — "sondas" especiais são adicionadas ao código do programa (ex.:
gprof). Desvantagem: diminui a velocidade de execução do programa. \n - Perfilamento por amostragem — em intervalos regulares, "observa" o programa e registra qual função está sendo executada no momento (ex.:
perf). Quase não diminui a velocidade do programa. \n
Existem também ferramentas para encontrar vazamentos de memória (Valgrind) e análise de cache. Para começar, é suficiente dominar gprof e perf.
Ferramenta 1: gprof — o clássico do perfilamento
\ngprof é um profiler integrado ao GCC. Ele funciona em duas etapas: coleta de dados e análise.
Como usar o gprof
\nPrimeiro, compile o programa com a flag -pg:
g++ -pg -o my_program my_program.cpp\nExecute o programa:
\n./my_program\nApós a execução, o arquivo gmon.out será gerado. Agora execute o gprof:
gprof my_program gmon.out > report.txt\nAbra o report.txt e observe a tabela:
Flat profile:\nEach sample counts as 0.01 seconds.\n % cumulative self self total\n time seconds seconds calls ms/call ms/call name\n 60.00 0.06 0.06 10000 0.01 0.01 slow_function\n 30.00 0.09 0.03 5000 0.01 0.02 medium_function\n 10.00 0.10 0.01 1 10.00 10.00 main\nNa coluna % time é mostrada a porcentagem de tempo que a função consumiu. No nosso exemplo, slow_function é a principal candidata para otimização.
Dica: Para programas pequenos, o gprof é excelente. Para projetos grandes, ele pode fornecer dados imprecisos devido às otimizações do compilador.
Ferramenta 2: perf — um poderoso amostrador para Linux
\nperf é um profiler integrado ao kernel Linux. Ele funciona por amostragem e quase não diminui a velocidade do programa. É ideal para sistemas em produção.
Uso básico do perf
\nCompile o programa com símbolos de depuração (flag -g):
g++ -g -o my_program my_program.cpp\nInicie o perfilamento:
\nperf record ./my_program\nApós a conclusão do programa, visualize o relatório:
\nperf report\nVocê verá uma interface interativa. Ao clicar em uma função, é possível ver quais linhas de código foram executadas com mais frequência. Exemplo de saída:
\nSamples: 1K of event 'cycles'\nEvent count (approx.): 250000000\nOverhead Command Shared Object Symbol\n 45.32% my_program my_program [.] slow_function\n 30.15% my_program my_program [.] medium_function\n 12.50% my_program libc-2.31.so [.] malloc\n 8.03% my_program my_program [.] main\nImportante: O perf requer privilégios de root para coletar dados do kernel