分支预测命中率需用 perf stat 同时采集 branches 和 branch-misses 计算:命中率 = 1 − branch-misses / branches;单独任一事件无意义,且受架构、权限、采样方式及上下文影响显著。

分支预测命中率不能直接“查看”,必须用 perf stat 同时采集两个硬件事件再手动计算:命中率 = 1 − branch-misses / branches。单独看任一数值都没意义,这是最常被忽略的前提。
为什么 perf stat -e branch-misses 单独运行没用
只读 branch-misses 是个绝对计数,脱离总分支数完全无法解释:
-
branch-misses为 0 可能只是因为程序根本没跑多少分支(比如空循环),不代表预测准 - 高吞吐服务中
branch-misses数值很大,但若branches更大,实际失败率可能低于 0.1% - 某些内核版本对
branch-misses的事件映射不稳定(尤其 Arm 平台),建议搭配 raw event 编码使用,例如 Intel Skylake+ 架构可用r1000000e8
正确采集命令:必须成对监控 branches 和 branch-misses
两个事件必须同时采集,且推荐用 group 模式保证采样一致性:
- 监控已有进程:
perf stat -e branches,branch-misses -p <pid></pid> - 启动新进程:
perf stat -e branches,branch-misses -- ./your_program - 要包含内核态分支,加
-k 1;默认只统计用户态 - 不同 CPU 微架构可能需显式指定前缀,如 Atom 系列用
cpu_atom/branch-misses,否则返回Operation not supported
权限和采样限制:perf_event_paranoid 和最小间隔
普通用户常遇到 Permission denied,本质是内核禁止非 root 访问 PMU:
- 临时修复:
echo 1 | sudo tee /proc/sys/kernel/perf_event_paranoid(比全程sudo perf更安全) - 秒级轮询不可行:PMU 计数器更新有硬件延迟,
perf_event_open开销在 ≤10ms 间隔下会反超数据价值 - 默认只监控当前线程;要覆盖整个进程所有线程,需在主线程创建前设
inherit = 1,或 fork 后显式 attach 到每个tid
真正容易被忽略的不是公式本身,而是“分支预测失败率”这个指标天生依赖上下文:同一段代码在不同输入分布、不同编译器优化等级(比如是否插入 likely/unlikely)、甚至不同 CPU 微架构上,数值差异可能达数量级。别拿单次结果下结论,重点看趋势和相对变化。


















