perf 是 linux 下 c++ 函数级性能分析最可靠、开销最小的工具,需编译时加 -g 保留符号信息,配合 perf record -g 采样和 perf report 分析调用链,结合火焰图直观定位热点。

perf 是目前 Linux 下对 C++ 程序做函数级性能分析最可靠、开销最小的选择,前提是编译时保留符号信息且运行环境可控。
编译时必须加 -g,否则 perf 看不到函数名
没有调试符号,perf report 里全是十六进制地址,根本没法定位到 workload2 或 std::vector::push_back 这类实际函数。这不是 perf 的限制,是你没给它“认人”的依据。
-
g++ -g -O2 main.cpp -o app就够用;-O3也行,但内联过度会导致调用栈变浅 - 避免
-fomit-frame-pointer(某些发行版默认开启),它会让-g失效一部分,影响调用栈还原 - 如果程序依赖动态库,确保那些库也带
-g编译,否则库内函数会显示为[unknown]
perf record -g 是函数级分析的最低门槛
不加 -g,perf report 只能列出平铺的函数耗时,看不出谁调用了谁;加了才能展开调用链,比如 main → parse_json → rapidjson::Parse 这种真实路径。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
perf record -g ./app最常用,采样默认事件cycles(CPU 周期) - 想聚焦缓存问题?改用
perf record -g -e cache-misses ./app - 分析系统调用开销?
perf record -g -e syscalls:sys_enter_read ./app - 注意:采样频率太高(如
-F 9999)可能引入偏差,一般默认即可
perf report 里怎么看懂“热点”在哪
输出是树状结构,默认按自顶向下(callee-oriented)排序。第一列 overhead 是该函数自身 + 所有子函数总耗时占比,第二列才是纯函数自身耗时(self)。很多人误把高 overhead 当成瓶颈,其实关键看 self 和调用深度。
- 如果
std::sort的self占比 45%,说明排序逻辑真慢;如果只有 2% 但overhead70%,那慢在它调用的比较函数里 - 按
→键可展开/折叠调用栈,q退出;/键支持搜索函数名 - 遇到大量
[unknown],先检查是否漏了-g,再确认 ASLR 是否关闭(echo 0 | sudo tee /proc/sys/kernel/randomize_va_space)
火焰图不是必须的,但能一眼看出调用瓶颈
perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > flamegraph.svg 这条命令生成的 SVG 文件,比文本报告直观十倍——宽的函数块就是热点,纵向堆叠就是调用链深度。
- 火焰图里窄但高的“尖刺”,往往是频繁调用的小函数(如
malloc、std::string::c_str()),值得查是否冗余调用 - 左右并排的宽块,说明多个分支并行耗时,适合做并发优化或算法重构
- 工具链需额外安装:
stackcollapse-perf.pl和flamegraph.pl来自 Brendan Gregg 的 FlameGraph 项目,别用错版本
真正卡住人的从来不是 perf 命令怎么敲,而是编译选项和运行时环境是否一致、符号是否完整、采样是否覆盖了真实负载路径。跑一次 perf record 前,先确认你复现的是用户反馈的那个慢场景,而不是一个空载 demo。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










