gprof适合单线程函数级粗粒度分析,需编译加-pg -g且禁用高优化;perf基于采样,支持多线程、优化代码和硬件事件,需保留-g符号并关闭ASLR以确保准确性。

用 gprof 或 perf 做 C++ 性能分析,核心是两步:编译时加调试和性能采集标记,运行后生成调用耗时报告。关键不在工具本身,而在你是否拿到了真实、可复现的热点路径。
gprof:适合函数级粗粒度分析
gprof 依赖编译器插桩(instrumentation),会改变程序行为,只适用于单线程、非内联、不带优化(或 -O1)的程序。它能告诉你每个函数花了多少时间、被谁调用、调用了谁。
- 编译时加 -pg -g,比如:g++ -pg -g -O0 main.cpp -o app
- 运行一次程序:./app(会自动生成 gmon.out)
- 生成报告:gprof app gmon.out > profile.txt
注意:-O2/-O3 下函数可能被内联或优化掉,gprof 就看不到它们;多线程下统计不准;动态链接库需单独编译加 -pg 才能进报告。
perf:Linux 下更轻量、更准确的采样式分析
perf 是基于硬件计数器的采样工具,几乎不影响运行速度,支持多线程、优化代码、系统调用和内核栈,是现代 C++ 性能分析的首选。
立即学习“C++免费学习笔记(深入)”;
- 记录运行时热点:perf record -g ./app(-g 开启调用图)
- 查看火焰图式汇总:perf report -g --no-children
- 导出供 FlameGraph 脚本使用:perf script > perf.script
常见技巧:用 perf record -e cycles,instructions,cache-misses 指定事件;加 --call-graph dwarf 提升 C++ 模板/内联函数的栈还原精度;对 release 版本分析务必保留 -g(调试符号),否则函数名全是 ???。
别跳过的关键准备动作
- 确保二进制含调试信息:strip 之前先备份,或编译时始终加 -g
- 关闭 ASLR(地址空间随机化)便于比对:echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
- 固定 CPU 频率避免频率缩放干扰:sudo cpupower frequency-set -g performance
- 用真实数据集跑,避免空循环或小样本导致的统计偏差
基本上就这些。gprof 快速上手但局限明显;perf 稍多几步配置,却能看清 cache miss、分支预测失败、锁竞争等深层问题。选哪个不重要,重要的是每次分析前确认符号没丢、样本够稳、环境没漂移。











