C++怎么使用perf工具_C++性能剖析教程【深入】

2次阅读

perf 不是 c++ 的一部分,需编译时加 -g -o2 -fno-omit-frame-pointer 以保留调试信息和帧指针;推荐用 –call-graph dwarf 模式,并用 perf report -n –children 分析真实热点。

C++怎么使用perf工具_C++性能剖析教程【深入】

perf 不是 C++ 的一部分,它压根不认 C++ 语法或符号——你得让编译器保留调试信息、关掉内联,否则看到的全是 _Z12computeStuffv???,根本没法定位到具体函数。

编译时必须加 -g -O2 -fno-omit-frame-pointer

perf 依赖 DWARF 调试信息和可靠的调用展开。默认 -O2 会内联函数、删帧指针,导致 perf report 显示“inlined function”或栈帧断裂。

  • -g:生成 DWARF,不然 perf 看不到源码行号和函数名
  • -fno-omit-frame-pointer:强制保留 %rbp(x86_64),让 perf record -g 能正确回溯调用链
  • 别用 -O3:过度优化会让热函数消失在 inlined frames 里,perf annotate 失效
  • 如果用了 LTO(-flto),务必加 -grecord-gcc-switches,否则链接后调试信息丢失

perf record -g --call-graph dwarf 比默认 fp 更靠谱

默认的 fp(frame pointer)模式在优化后极易断栈;dwarf 模式读取 .debug_frame,能绕过被优化掉的帧指针,对现代 C++ 更友好。

  • 运行命令:perf record -g --call-graph dwarf -e cycles,instructions ./my_app
  • 注意:需要 kernel 支持 CONFIG_DEBUG_INFO_DWARF4=y(多数发行版已启用)
  • 如果提示 failed to open Event ... No such file or Directory,说明内核没开 CONFIG_PERF_EVENTS,不是你代码的问题
  • perf script 输出的是原始采样流,适合 grep 函数名,但别直接 human-read

perf report -n --children 看清谁真正吃 CPU

perf report 默认按“采样点所在函数”排序,容易误判——比如 std::vector::push_back 高,实际是上层循环调用它太多次。用 --children 才能看“这个函数及其所有子调用共占多少周期”。

立即学习C++免费学习笔记(深入)”;

  • perf report -n --children:显示自顶向下累积开销,Children 列才是关键指标
  • -n 显示采样次数,比百分比更稳定(尤其短时间采样)
  • 遇到 __libc_start_main 占比异常高?大概率是程序跑得太快,perf 没采到有效样本——加 perf record -F 99 提高采样频率,或用 sleep(1) 延长热点持续时间
  • 如果 perf report 里全是地址(如 0x4012a3),说明 -g 没生效,或者二进制被 strip 过

最常被忽略的一点:perf 分析的是整个进程,包括 STL 内部、内存分配器、甚至动态链接器。想聚焦自己的代码,得用 perf report --symbol-Filter=my_namespace::my_function 过滤,而不是靠眼睛扫几百行 std:: 调用。

text=ZqhQzanResources