当前位置:首页 > 文章列表 > 文章 > linux > perf stat -j 怎样导出硬件计数器 JSON

perf stat -j 怎样导出硬件计数器 JSON

来源:17golang原创 2026-11-07 00:11:23 0浏览 收藏

如果只在终端看 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 提供的输出选项。

perf stat 事件集合与 JSON 记录之间的静态结构关系说明图
图1:perf stat 的事件集合、采集器与 JSON 记录之间的静态关系;这是原创说明图,不是终端截图。

图中把“事件定义”和“输出记录”分开看: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% 时要考虑复用和调度影响

开启间隔统计、重复运行或其它聚合选项时,记录还可能带有时间、方差或聚合标识。后处理代码应允许字段缺失,不要把所有行都强制转换成同一种业务对象。

perf stat JSON 记录中事件、计数值和运行比例字段的静态关系图
图2:JSON 记录的核心计数、上下文字段和后处理关注点;这是字段关系示意图,不是运行结果截图。

交给 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 解析仍按字段名处理;若开启聚合选项,则额外保存对应的线程标识。

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