火焰图空白主因是采样频率过低或权限不足导致无法读取用户态调用栈;C++程序若未加-g和-fno-omit-frame-pointer编译,符号解析失败也会造成全[unknown]或__libc_start_main占顶。

perf record 采样时为什么程序没明显卡顿但火焰图却空白?
因为默认采样频率太低,或 perf 没权限读取用户态调用栈。C++ 程序(尤其启用 -O2 或 -O3)内联频繁,若未编译带调试信息,perf 无法解析符号,火焰图里全是 [unknown] 或 __libc_start_main 占满顶层。
- 编译时务必加
-g -fno-omit-frame-pointer(后者对帧指针关键,perf依赖它做栈回溯) - 用
sudo perf record -F 99 -g -- ./your_program:其中-F 99避免与系统定时器冲突,-g启用调用图采样 - 确认程序实际运行了足够时间(至少 5 秒),否则采样点太少,
perf script输出为空
火焰图里全是 C++ 模板符号或 ??:? 怎么办?
这是符号解析失败的典型表现——perf 能采集到地址,但找不到对应函数名。不是代码问题,是工具链链路断了。
- 检查是否漏掉
-g编译:运行file your_program,输出中必须含with debug_info - 确保没 strip 过二进制:
nm -C your_program | head -5应能看到可读函数名,而非全是U或乱码 - 如果用了静态链接 STL(如
-static-libstdc++),需确保 libstdc++ 也带调试符号(通常系统包不提供,建议改用动态链接) - 临时补救:用
perf report --no-children看原始符号,确认哪些函数名能显示,再针对性修复编译选项
生成火焰图时 stackcollapse-perf.pl 报错 “No stack counts found”
说明 perf script 输出格式异常,常见于内核版本过低或 perf 版本不匹配。
- 先运行
perf script | head -10,看输出是否含类似your_program 12345 12345.678901: 123456 cycles:u:的行;若全是空行或报错,说明perf record根本没采到数据 - 升级 perf:Ubuntu/Debian 用
sudo apt install linux-tools-$(uname -r),CentOS/RHEL 用sudo yum install perf,避免用系统自带老旧版本 - 某些容器环境禁用
perf_event_paranoid,执行echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid解锁(仅限开发机)
火焰图顶部宽平、底部窄尖,热点不集中?
这不是图的问题,是程序本身行为:大量短生命周期线程、频繁系统调用、或 I/O 阻塞导致 CPU 时间片被切碎。火焰图如实反映调度碎片化,但会掩盖真实瓶颈。
立即学习“C++免费学习笔记(深入)”;
- 优先用
perf record -e cycles,instructions,cache-references,cache-misses多事件采样,再用perf report -n查看各函数的 cache miss 率,比单纯看 CPU 时间更准 - 对多线程程序,加
--call-graph dwarf替代-g(需 libdw 支持),能更好处理线程切换和栈丢失 - 若怀疑是锁竞争,直接采样
perf record -e sched:sched_stat_sleep,sched:sched_stat_iowait,再用perf script提取睡眠原因
真正卡住性能的,往往不是最宽的函数块,而是那些在火焰图里反复出现、每次只占 1–2% 但总和超 30% 的小函数——它们常是模板实例化爆炸、无意义拷贝、或隐式类型转换触发的临时对象构造。别只盯着顶部,得横向扫完整层。


















