必须加 -g 和 -fno-omit-frame-pointer 并用 -o2 编译,否则 perf report 会出现 [unknown] 或调用栈断裂;-o0 导致内联禁用、热点漂移,-o3 过度内联破坏调用关系。

perf record -g 采样前必须加 -g 和 -O2
不加 -g,perf report 里全是 [unknown];只加 -g 但用 -O0 编译,内联被禁用、函数边界失真,热点会漂移。真实瓶颈常藏在 std::vector::push_back 或 std::string::operator+= 这类高频小函数里,而 -O0 会让它们“膨胀”成一堆冗余调用,掩盖真实开销。
推荐编译命令:g++ -O2 -g -fno-omit-frame-pointer。-fno-omit-frame-pointer 不是可选——它让 perf 能正确展开调用栈,尤其对 inlined 函数和模板实例化有效;某些 GCC 版本在 -O2 下默认省略 frame pointer,一漏就断链。
- 别用
-O3:过度内联会让perf report显示大量???或扁平函数名,调用关系丢失 - Release 模式下 inline 函数“消失”?不是真的消失,是符号被折叠——用
compiler explorer看汇编确认实际行为 - 确保没
strip二进制:file your_program输出里要有not stripped
perf record -g 后别直接 perf top
perf top 是实时视图,关掉就丢数据,且不记录调用栈——你看到的只是当前 CPU 正在执行的指令地址,没法回溯是谁调了它。真正要保存上下文、后续反复分析,必须用 perf record -g 生成 perf.data。
常见错误是跑完 perf record -g ./app 后,立刻切到另一个终端敲 perf top -p $(pidof app),结果发现两个视图对不上:前者有完整调用链,后者只有平铺函数名,还夹杂大量 __libc_start_main。
- 多线程程序默认只采主线程:加
-a(全系统)或-p PID(指定进程)才能覆盖所有线程 - 短时程序(-F 99 提高频率(默认 4KHz 对短任务太稀疏)
- 避免在容器里跑 perf:cgroup 限制可能干扰事件计数,优先在宿主机或特权容器中运行
perf report -n --no-children 看 Self 开销
perf report 默认显示 “Children” 总耗时,容易误判——比如 main 占比 95%,但它只是调度入口,真正干活的是它下面的 process_request。用 --no-children 才能聚焦 “Self” 列,即函数自身代码执行时间,这才是第一级瓶颈信号。
按 Enter 展开调用栈后,重点关注那些 Overhead > 5% 且不是系统调用(如 read、epoll_wait)的 C++ 函数。若某函数 Self 很低但 Children 高,说明它只是胶水层,瓶颈在子函数里,继续向下钻。
- 火焰图里顶部宽但颜色浅?可能是
futex_wait或pthread_cond_wait——这是 Off-CPU 等待,不是 CPU 瓶颈,需换offcpu工具分析 - 大量
std::allocator::allocate出现在 Self 列?说明内存分配热点,不是算法问题,是对象生命周期或容器预分配策略问题 -
perf report -F comm,dso,symbol可过滤掉内核符号,聚焦你的二进制和 so 文件
火焰图比文本报告更能暴露高频小函数
文本报告里 std::string::c_str() 单次开销可能只有 0.02%,但火焰图横向宽度反映总占比——如果它在循环里被调用百万次,就会变成一条又宽又矮的“横条”,一眼揪出。
生成流程必须严格:先 perf script 导出原始栈,再经 stackcollapse-perf.pl 折叠(漏这步,flamegraph.pl 读不懂),最后输出 SVG。浏览器打开后,鼠标悬停看精确占比,点击函数名可跳转源码行(前提是编译带 -g 且路径未变)。
- 火焰图里出现大片灰色?说明符号缺失:检查是否
g++ -g编译,以及是否strip过二进制 - 调用栈过深(>20 层)导致火焰图“瘦高”难读?加
--max-depth 15限制深度,或用perf report --call-graph dwarf,0.01过滤低频路径 - 多线程火焰图混在一起?用
perf script -F comm,pid,tid,cpu,time,event,ip,sym加字段区分线程上下文
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











