C++怎么进行性能分析_C++perf工具教程【调优】

1次阅读

perf record 看不到函数名是因为二进制缺少调试信息(需编译加 -g),导致符号无法解析,表现为 [unknown] 或 __libc_start_main,应检查 debuginfo 是否存在、未被 strip、build-id 是否完整,并确保 cmake 构建类型为 relwithdebinfo。

C++怎么进行性能分析_C++perf工具教程【调优】

perf record 采样时为什么看不到函数名?

默认编译没带调试信息,perf 只能拿到地址,没法映射到符号。不是 perf 有问题,是你的二进制缺 -g-gdwarf-4

  • 编译必须加 -g(推荐 -g -O2,调试信息和优化不冲突)
  • 如果用 CMake,确认 CMAKE_BUILD_TYPE 不是 Release(它默认关 -g),改用 RelWithDebInfo
  • 动态库也要单独带调试信息,否则 perf report 进不去 SO 里的函数
  • 检查是否被 strip 过:file your_binary 输出里要有 “with debug_info”

perf report 显示的开销集中在 [unknown][.] __libc_start_main

这是符号解析失败的典型表现,常见于内联函数、JIT 代码或未加载 debuginfo 的系统库。

  • 先运行 perf buildid-list -i perf.data 看有没有缺失的 build-id;再用 perf buildid-cache -v --add /lib/x86_64-linux-gnu/libc.so.6 补全
  • 若程序用了 std::functionLambda,GCC/Clang 默认会内联,perf 就只看到调用点,看不到实际逻辑 —— 加 -fno-inline-functions 临时编译可验证
  • 容器环境要注意:宿主机跑 perf record -p $(pidof your_app),但容器里没装 debuginfod 或没挂载 /usr/lib/debug,也会显示 [unknown]

怎么只分析某个函数的 CPU 时间,而不是整个进程?

perf record 本身不支持函数级过滤,得靠 --call-graph + 后处理,或者用 perf probe 打点。

  • 最稳的方法:用 perf record -e cycles,instructions -g --call-graph dwarf -- ./your_program,然后 perf report --no-children -g --sort comm,dso,symbol,再用 / 搜索目标函数名
  • 想精确卡住某函数入口/出口,用 perf probe 'your_namespace::your_function'(需有调试信息),再 perf record -e probe:your_function*
  • 注意:perf probe 对模板实例化函数支持有限,比如 std::vector<int>::push_back</int> 很可能找不到,优先试具体实现函数(如 __gnu_cxx::new_allocator::allocate

perf 跟踪线程程序时,CPU 占用率虚高或线程 ID 对不上?

perf record 默认按线程采样,但线程复用、pthread_create 后快速退出等情况会让 perf script 输出的 tid 和你 ps 看到的不一致。

  • -t 参数显式指定 tid:perf record -t -p $(pgrep -f "your_binary"),避免父进程干扰
  • 多线程高频锁竞争场景,cycles 事件会严重失真(大量停顿在 futex_wait_queue_me),换用 cpu/Event=0x02c4,umask=0x20,name=stalls_ldm_full/(Intel)这类微架构事件更准
  • perf record -e task-clock,context-switches,page-faults 是比单纯看 cycles 更可靠的吞吐视角

实际调优时,最常被跳过的一步是验证「问题是否复现」:同一份 perf.data 在不同机器上 perf report 结果可能不同,因为 kernel 版本、perf 版本、甚至 /proc/sys/kernel/perf_event_paranoid 设置都影响符号解析深度。别急着改代码,先确认你能稳定看到那个热点函数。

text=ZqhQzanResources