当前位置:首页 > 文章列表 > 文章 > linux > perf stat 组合硬件计数器分析 CPU 周期

perf stat 组合硬件计数器分析 CPU 周期

来源:17golang原创 2026-10-10 21:04:25 0浏览 收藏

分析 CPU 周期时,先用 perf stat 同时采集 cycles 和 instructions,再用周期数除以指令数得到 CPI。这样能把“程序慢”拆成可观察的计数器关系,而不是只看一次墙上时钟时间。Linux 内核文档说明,perf stat 会借助现代 CPU 中的硬件计数器统计软硬件事件。

官方文档:https://docs.kernel.org/admin-guide/workload-tracing.html

下面的示例只展示命令写法和解释方法,配图是静态说明图,不是本机运行截图,也不代表某台机器已经产生了固定数值。

先把 perf stat 的三层对象分开

这条命令里有三个容易混淆的对象:

  • 事件名:例如 cycles、instructions 和 branches,描述想数什么。
  • PMU 计数器:CPU 提供的性能监控单元,负责在硬件层累计事件。
  • perf stat:把事件配置、启动/停止计数、缩放和结果展示串起来的用户态工具。

因此,看到某个事件显示为不可用时,首先要判断是 CPU、内核、虚拟机还是权限没有提供它,而不是立刻把它解释为程序没有执行相关操作。

工作负载通过 perf stat 选择 cycles、instructions 和 branches,再由 CPU PMU 计数器统计并输出结果的结构说明图
图1:结构说明图,展示 perf stat 选择硬件事件并交给 CPU PMU 计数器统计的关系。

先用 perf list 确认当前机器能看到什么

硬件事件不是所有机器都完全相同。先列出当前 perf 能识别的事件,再决定组合方式:

# 列出当前环境可见的事件,先确认名称再写统计命令
perf list

# 只筛选周期、指令和分支相关事件,便于快速阅读清单
perf list | grep -E 'cycles|instructions|branches'

如果清单中没有预期的通用事件,可能是 CPU PMU 暴露方式不同、内核配置不同,或者运行在限制硬件计数器的虚拟机里。不要把网上另一台 CPU 的事件别名原样搬过来;以当前机器的 perf list 结果为准。

用一条命令组合 CPU 周期和指令数

对一个稳定的工作负载,可以先使用最小组合:

# 同时统计 CPU 周期与退休指令,sleep 只是一个占位工作负载
perf stat -e cycles,instructions -- ./your-program --input sample.dat

# 再加入分支事件,观察控制流相关的额外线索
perf stat -e cycles,instructions,branches,branch-misses -- ./your-program --input sample.dat

-e 后用逗号分隔事件。-- 用来明确后面的内容是被测程序及其参数,避免程序自己的参数被 perf 误解。示例中的程序名、参数和文件只是写法占位,实际采集时应替换成可以重复运行的真实工作负载。

硬件计数器数量有限时,perf 可能分时复用事件,结果会带有缩放信息;如果事件组合过多,还可能出现无法调度或某个计数器不可用。第一轮建议只保留能回答当前问题的两个到四个事件。

让每次采集可以被比较

单次运行只能说明一次运行的计数结果。要比较优化前后,至少固定输入、参数、CPU 亲和性和重复次数,并把结果保存成机器可读格式:

# 使用 CSV 输出,便于保存多次运行的计数结果
perf stat -x, -o perf-baseline.csv -e cycles,instructions -- ./your-program --input sample.dat

# 绑定到同一 CPU 集合,减少调度位置变化带来的噪声
taskset -c 2-3 perf stat -r 5 -x, -e cycles,instructions -- ./your-program --input sample.dat

-r 5 让 perf 重复运行工作负载并汇总结果,-x, 用逗号作为字段分隔符,-o 将统计输出写入文件。这里的重复运行是测量设计,不是质量保证;仍要确保工作负载本身没有随机输入、缓存预热差异或后台任务干扰。

如果程序会改变系统状态,不能简单重复执行同一个命令。可以准备只读输入、隔离输出目录,或让程序提供可重复的基准模式。

用 CPI 把两个计数器变成判断线索

得到计数后,用下面的关系做第一层判断:

# CPI 表示平均每条退休指令消耗的 CPU 周期
CPI = cycles / instructions

CPI 较高通常意味着流水线等待、缓存未命中、分支预测失误或其他微架构停顿更明显;CPI 较低并不自动等于程序更快,因为总指令数、频率、并发度和输入规模也会影响总耗时。更稳妥的比较方式是同时观察:

观察项作用不要单独推出的结论
cycles估计工作负载消耗的处理器周期不能单独代表墙上时间
instructions观察退休指令规模不能单独代表每条指令成本
CPI把周期与指令规模联系起来不能直接定位具体代码行
branch-misses观察分支预测失败线索不能证明唯一瓶颈就是分支
cycles 与 instructions 推导 CPI 并结合基线比较,同时受 perf_events、CAP_PERFMON 和内核配置权限影响的关系说明图
图2:关系说明图,展示 CPI 的静态推导和 perf_events 权限边界;它不是运行输出。

把权限和虚拟化边界排除在性能结论之外

perf_events 访问受到内核安全策略约束。Linux 内核文档指出,CAP_PERFMON 可以为非 root 进程提供性能监控相关能力,使用过大的管理员权限并不是首选方案。生产环境还应考虑计数结果中可能包含 CPU 型号、进程名、路径和硬件配置等信息。

# 查看当前 perf 工具和内核环境,记录测量上下文
perf --version
uname -a

# 查看当前进程的 perf_event 相关限制;不同发行版可能有不同权限策略
cat /proc/sys/kernel/perf_event_paranoid

遇到 Permission denied、事件显示 或计数器无法调度时,按“权限—内核配置—CPU/虚拟机能力—事件数量”顺序排查。不要为了让命令有输出就直接使用 root,也不要把权限放宽后的结果与普通权限下的结果无条件混合比较。

一份可复用的最小检查清单

  1. 先用 perf list 确认事件名称和当前环境能力。
  2. 从 cycles,instructions 开始,按问题需要加入分支或缓存事件。
  3. 固定输入、CPU 集合、重复次数和输出格式,再比较优化前后。
  4. 同时保存 cycles、instructions、CPI 与墙上时间,避免单指标判断。
  5. 把权限、虚拟机、内核策略和计数器复用记录在测量说明里。

常见问题

为什么 cycles 和 wall-clock time 不一样?

cycles 是处理器性能计数器的事件数量,wall-clock time 是经过的实际时间,两者受到频率变化、调度、并行线程和系统空闲时间等因素影响。分析 CPU 计算量时看 cycles,评估用户感知延迟时仍要保留实际耗时。

事件太多时为什么会出现缩放或不可用?

硬件 PMU 的可编程计数器数量有限,perf 可能在事件之间分时复用;当某些事件无法同时调度时,结果可能被缩放或直接不可用。减少事件组合并分组测量,通常比盲目添加事件更容易得到可解释结果。

CPI 高是否就说明缓存有问题?

不一定。CPI 是综合指标,缓存等待、分支预测、流水线资源竞争和内存访问都可能影响它。应再选择与假设对应的缓存、分支或停顿事件,并与相同输入下的基线比较。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
os/exec Cmd.Cancel 设计超时后的退出动作os/exec Cmd.Cancel 设计超时后的退出动作
上一篇
os/exec Cmd.Cancel 设计超时后的退出动作
Import Maps 统一浏览器端依赖别名
下一篇
Import Maps 统一浏览器端依赖别名
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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模型性能。
    408次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    486次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    494次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    443次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    270次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码