当前位置:首页 > 文章列表 > 文章 > linux > Linux perf stat 怎样区分分支预测失败和缓存未命中

Linux perf stat 怎样区分分支预测失败和缓存未命中

来源:17golang原创 2026-11-14 06:34:16 0浏览 收藏

Linux 性能排查里,branch-misses 和 cache-misses 经常一起出现,但它们回答的是两件不同的事:前者统计处理器对分支方向的预测失误,后者通常表示某一级缓存访问没有命中,且具体映射会随 CPU 和 PMU 改变。要区分它们,先在同一次 perf stat 测量中保留各自的分子和分母,再结合本机的 perf list 解释事件。

官方地址:https://perf.wiki.kernel.org/

下面的示例只围绕硬件计数器、采样和架构差异展开。假设 ./workload 是已经准备好的、可以重复运行的程序,不把示例命令的数字当成固定运行结果。

先把两类计数器放在同一次测量里

最小的对照组是四个通用事件:

  • branches:已执行或退休的分支指令计数,具体映射由平台决定。
  • branch-misses:分支预测失败的计数。
  • cache-references:缓存访问参考计数,可能包含预取或一致性相关行为。
  • cache-misses:缓存未命中计数,通常接近最后一级缓存未命中,但不能脱离本机 PMU 说明。
# 把分支和缓存的分子、分母放到一次统计中,便于比较同一轮工作负载
perf stat -e '{branches,branch-misses,cache-references,cache-misses}' -- ./workload

# 先查看当前 perf 能解析哪些同名事件和描述,避免直接猜测硬件含义
perf list branch-misses
perf list cache-misses
perf stat 与分支、缓存通用计数器之间关系的静态说明图
图1:perf stat、分支计数器与缓存计数器的静态关系说明图,不是截图或运行证据。

这里的重点不是把四个事件拼成一个“综合分数”,而是让两个比例使用同一次运行的上下文。若工作负载有明显冷启动、输入随机性或后台干扰,至少先让它能稳定重复,再比较多次测量的趋势。

用各自的分母读懂两个比例

分支和缓存不能使用同一个分母。最常见的解释方式是:

观察对象计算方式能说明什么不能直接说明什么
分支预测失败率branch-misses / branches分支中有多少次没有按预测路径命中不能单独换算成总耗时或每次失误的固定代价
缓存未命中率cache-misses / cache-references被计数的缓存参考中有多少没有命中不能默认它只代表 L1,也不能代表所有内存停顿

例如,分支比例明显升高而缓存比例稳定,优先检查条件分支、间接调用、输入分布和循环控制;缓存比例升高而分支比例稳定,优先检查访问局部性、数据布局、工作集大小和指针追踪。两个比例都升高时,不要立刻断言“CPU 同时被两种问题拖慢”,应继续确认事件是否被正确调度以及工作负载是否发生了输入变化。

可以让 perf stat 重复执行同一个命令,用平均值和离散程度观察趋势:

# 重复同一程序五次;固定 CPU 只是减少迁移噪声,不会修正事件语义
taskset -c 2 perf stat -r 5 \
  -e '{branches,branch-misses,cache-references,cache-misses}' \
  -- ./workload

# 只统计用户态,减少内核路径对应用工作负载的混入
perf stat -e 'branches:u,branch-misses:u,cache-references:u,cache-misses:u' -- ./workload

先排除计数器没有完整覆盖

CPU 的硬件计数器数量有限。当请求的事件多于可同时调度的计数器时,perf 会进行时间复用;输出中的运行时间比例会影响计数的可信度。把多个事件放进组可以要求它们尽量一起调度,但事件太多、PMU 不支持组合或计数器有特殊限制时,组也可能无法运行。

# 让四个事件尽量作为同一组调度;组无法满足时应按提示拆成两轮
perf stat -e '{branches,branch-misses,cache-references,cache-misses}' -- ./workload

# 使用详细模式查看事件解析、PMU 和附加指标,辅助解释 not counted 或覆盖率提示
perf stat -v -e '{branches,branch-misses,cache-references,cache-misses}' -- ./workload

遇到 not counted、覆盖率很低或两次运行的启用时间差异很大时,不要拿结果直接做优化结论。可以将事件拆成分支组和缓存组分别运行,并保持输入、CPU 亲和性、程序参数和重复次数一致。这样得到的两轮数字不再是同一时刻,但通常比一个没有完整计数的混合结果更容易解释。

用 perf list 确认架构和 PMU 边界

perf 提供的是通用事件名称,底层仍然由当前 CPU 的 PMU 负责映射。Linux 文档对通用缓存未命中的描述使用了“通常是最后一级缓存”的限定;同一个名字在不同微架构、内核版本或虚拟机环境里,可能对应不同的硬件事件。

# 查看事件的长描述、解析细节以及当前系统暴露的 PMU 名称
perf list --details branch-misses
perf list --details cache-misses
ls /sys/bus/event_source/devices/

# 混合架构可能同时暴露不同 PMU;只有本机列出对应 PMU 时才使用这种限定写法
perf stat -e 'cpu_core/branch-misses/,cpu_core/cache-misses/' -- ./workload
perf stat -e 'cpu_atom/branch-misses/,cpu_atom/cache-misses/' -- ./workload
perf 通用事件映射到 cpu_core 与 cpu_atom PMU 的静态说明图
图2:通用事件别名、PMU 与解释层之间的静态映射图,不是截图或运行证据。

如果命令提示事件不存在,先把它当成平台差异处理,而不是修改标题中的概念。记录 CPU 型号、内核版本、perf 版本和 perf list 中的实际事件名,再选择厂商 PMU 文档里的原生事件。不要把某个 Intel 事件编码原样搬到 AMD、Arm 或虚拟 CPU 上。

需要定位代码时再切换到采样

perf stat 适合回答“这次工作负载发生了多少次、比例怎样”。当比例已经指向分支或缓存问题,但还不知道哪个函数贡献最大时,才用 perf record 采样热点。采样周期、权限和 PMU 支持同样依赖环境,不能把采样点数量当作精确事件总数。

# 以分支误预测事件做采样,周期只是示例,应按本机事件支持情况调整
perf record -e branch-misses:u -c 100000 -- ./workload

# 读取采样报告,观察热点函数而不是把采样数量当成精确总次数
perf report

缓存方向也可以采用相同思路,但更应该先确认采样事件的粒度。某些平台能提供更细的 L1、LLC、加载来源或精确事件,某些平台则只能提供较粗的通用别名。文章标题中的“缓存未命中”因此应理解为一次可解释的计数起点,而不是对所有缓存层的统一定义。

一张表完成结果判断

现象先看什么下一步
branch-misses / branches 偏高输入分布、条件分支、间接跳转用采样或反汇编定位贡献函数,再评估分支改写是否值得
cache-misses / cache-references 偏高访问步长、工作集、数据布局、缓存层级确认具体缓存事件和层级,再比较布局或批处理方案
两个比例都不稳定重复次数、CPU 迁移、输入和事件覆盖率先固定测量条件,必要时拆组分两轮采集
事件不存在或值异常perf list、PMU 名称、虚拟化和权限改用本机支持的通用或原生事件,不复制其他 CPU 的编码

真正有用的结论应该同时写出事件名、分母、运行覆盖率、CPU/内核环境和重复方式。只贴一行 cache-misses 的绝对值,既不能证明是 LLC 问题,也不能证明优化后一定更快。

相关问题

branch-misses 越多就一定越慢吗?

不一定。失误的代价取决于微架构、分支位置、并行度和工作负载,比例只能帮助发现方向,不能直接换算耗时。

cache-misses 能代表 L1 缓存未命中吗?

不能直接这样读。通用事件通常更接近最后一级缓存未命中,但实际定义要以本机 perf 描述和 CPU PMU 文档为准。

为什么 perf stat 输出里会出现百分比或 not counted?

事件可能被时间复用、无法同时调度或受到权限和 PMU 限制。先降低事件数量、拆分测量并检查详细事件解析,再比较结果。

什么时候需要 perf record?

当 stat 已经确认某类计数偏高,但还需要知道是哪个函数或指令位置贡献时,再转向采样;stat 与 record 的数字不能混为同一种度量。

官方参考

  • https://www.kernel.org/doc/html/latest/admin-guide/workload-tracing.html
  • https://man7.org/linux/man-pages/man1/perf-stat.1.html
  • https://man7.org/linux/man-pages/man1/perf-list.1.html
  • https://man7.org/linux/man-pages/man2/perf_event_open.2.html
版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Linux io_uring 与 epoll 在大量短连接下怎么选择Linux io_uring 与 epoll 在大量短连接下怎么选择
上一篇
Linux io_uring 与 epoll 在大量短连接下怎么选择
nftables 拼接集合怎样按地址和端口同时匹配
下一篇
nftables 拼接集合怎样按地址和端口同时匹配
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    1019次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    1021次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1155次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1122次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    963次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码