perf stat -j 怎样导出硬件计数器 JSON
来源:17golang原创
时间:2026-11-07 00:11:23 333浏览 收藏
如果只在终端看 perf stat,表格很直观;一旦要把 cycles、instructions 或缓存事件交给脚本,按空格切列就会很脆弱。更稳妥的做法是使用 -j 输出 JSON,再根据字段名处理。
直接答案是:在 perf stat 后加入 -j,并注意统计结果通常写到标准错误。例如:
# -j 输出机器可读记录;2> 把 perf stat 的结果保存为 JSON 文件 perf stat -j -e cycles,instructions -- ./bin/demo 2> perf-stat.json
官方地址:https://man7.org/linux/man-pages/man1/perf-stat.1.html
这篇文章只讨论 JSON 输出与字段后处理,不把 -j 当成线程聚合或 CPU 核心聚合选项。输出格式变得稳定,并不代表硬件事件一定能同时运行或一定有权限访问。
先分清 perf stat JSON 的输出边界
perf stat 负责读取性能事件并打印统计信息,默认的人类可读表格适合快速查看,却不适合让程序依赖列位置。-j 把每条统计记录表达成 JSON 字段,后处理脚本就可以按键名取值。
另一个容易漏掉的点是输出流。很多 perf 统计结果会写到标准错误,所以只用 1> perf-stat.json 可能得到空文件,正确做法是同时重定向 stderr,或者使用 perf 提供的输出选项。

图中把“事件定义”和“输出记录”分开看:JSON 只描述采集结果的字段,不替你决定应该测量哪个事件,也不保证不同处理器都支持同名事件。
用 -j 导出硬件计数器记录
最小命令可以从两个固定事件开始:
# 选择两个常见硬件事件,并把被测程序放在 -- 后面 perf stat -j -e cycles,instructions -- ./bin/demo 2> perf-stat.json # 只查看 JSON 文件中的前几行,避免把它误当成普通表格解析 sed -n '1,5p' perf-stat.json
cycles 和 instructions 是事件名,-- 用来分隔 perf 参数与被测命令。若要统计一个已经存在的进程,可以改用 -p PID;若关注某个线程,则应使用与目标 TID 对应的参数,但这属于监控对象选择,不是 JSON 格式本身。
如果一次加入太多事件,内核可能需要在硬件计数器之间复用它们。此时 JSON 仍然可以生成,但结果中的运行比例会提醒你该事件并非全程占用计数器。
按字段解释 JSON 记录
常见记录可以按下面几组字段理解:
| 字段 | 用途 | 处理建议 |
|---|---|---|
event | 事件名称 | 作为结果的稳定标识,不要依赖输出顺序 |
counter-value | 计数值 | 读取前先确认不是空值或不可用标记 |
unit | 显示单位 | 与计数值一起保存,避免跨事件误比较 |
event-runtime | 事件实际运行时间 | 用于判断统计覆盖范围 |
pcnt-running | 事件运行占比 | 低于 100% 时要考虑复用和调度影响 |
开启间隔统计、重复运行或其它聚合选项时,记录还可能带有时间、方差或聚合标识。后处理代码应允许字段缺失,不要把所有行都强制转换成同一种业务对象。

交给 jq 或脚本做稳定后处理
如果只想提取有效的事件记录,可以先过滤具有 event 的对象,再读取计数值和运行比例:
# 过滤非事件行,并以制表符输出便于继续进入脚本或表格 jq -r 'select(.event != null) | [.event, ."counter-value", .unit, ."pcnt-running"] | @tsv' \ perf-stat.json
这里没有把 JSON 转回“按列切分”的文本,而是保留字段语义。生产脚本还应区分三种情况:事件存在且有计数值、事件存在但计数值不可用、以及这一行只是额外的摘要或上下文信息。
import json
from pathlib import Path
# 只接收有事件名的记录,并保留运行比例供后续判断
records = []
for line in Path("perf-stat.json").read_text(encoding="utf-8").splitlines():
try:
item = json.loads(line)
except json.JSONDecodeError:
# 日志中若混入非 JSON 行,跳过并交给上层记录告警
continue
if item.get("event") is not None:
records.append({
"event": item.get("event"),
"value": item.get("counter-value"),
"unit": item.get("unit"),
"running": item.get("pcnt-running"),
})
代码故意保留 None,因为“字段缺失”和“计数值为零”不是同一件事。若业务要比较两个事件,还应先统一单位并检查运行比例,而不是只比较数值大小。
处理事件组与硬件限制
JSON 解决的是输出表达,不会绕过 PMU 的硬件限制。加入的事件太多时,perf 会进行时间复用;事件组则要求相关事件尽量一起调度。若记录中的 pcnt-running 较低,说明该事件并没有在整个测量期间运行,结果应标记为“需要谨慎解释”。
# 用事件组表达需要尽量同时调度的两个事件,并保留 JSON 输出
perf stat -j -e '{cycles,instructions}' -- ./bin/demo 2> grouped.json
# 记录命令本身,便于把事件集合与 JSON 结果一起归档
printf '%s\n' 'perf stat -j -e {cycles,instructions} -- ./bin/demo' > grouped.command.txt
另外,权限、内核配置、虚拟机环境和处理器型号都可能影响事件是否可用。出现权限错误或某个事件不可用时,应先处理环境与事件选择,不要把问题误归咎于 JSON 解析。
几个容易踩到的边界
| 现象 | 原因 | 处理方式 |
|---|---|---|
| 重定向文件为空 | 只重定向了 stdout | 使用 2> 接收统计输出 |
| 脚本偶尔取不到值 | 把摘要行当成事件行 | 先判断 event 是否存在 |
| 计数值看起来偏小 | 事件复用或运行比例不足 | 结合 pcnt-running 与事件数量判断 |
| 不同机器结果不可比 | 硬件事件和单位存在差异 | 保存 CPU、命令和事件集合元数据 |
总结:把 JSON 当作带边界的结果接口
perf stat -j 适合把硬件计数器结果交给脚本:先正确接收标准错误,再按字段名读取 event、counter-value 与 pcnt-running。后处理时允许字段缺失,测量解释时同时关注事件复用、权限和处理器差异。
最重要的边界是:JSON 只让输出更适合机器读取,不会让硬件事件自动变得可用,也不会替代对测量覆盖率的判断。
相关问题
为什么 perf stat -j 生成的文件不是标准单个 JSON 数组?
perf stat 的 JSON 输出通常按记录逐行表达,便于持续输出和增加上下文字段。读取时可以按行解析,不要先假设整个文件一定包在数组中。
pcnt-running 低于 100% 还能比较吗?
可以作为线索,但不能直接当作同等可信的完整测量。先减少事件数量或使用合理的事件组,再结合运行比例解释结果。
只想看某个线程时要改 JSON 解析吗?
通常不用。监控对象由 perf 的进程或线程参数决定,JSON 解析仍按字段名处理;若开启聚合选项,则额外保存对应的线程标识。
-
332 收藏
-
426 收藏
-
329 收藏
-
377 收藏
-
412 收藏
-
451 收藏
-
307 收藏
-
145 收藏
-
369 收藏
-
406 收藏
-
183 收藏
-
259 收藏
-
394 收藏
-
218 收藏
-
372 收藏
-
436 收藏
-
226 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习