当前位置: 首页 > news >正文

【perf】perf工具的使用生成火焰图

文章目录

  • 1. What is perf?
  • 2. perf使用
    • 2.1 perf的子工具集
    • 2.2 常用指令
      • perf list
        • 指令格式
        • 参数
        • perf中事件分类
        • 使用示例
      • perf stat
        • 指令格式
        • 参数
      • perf top
        • 指令格式
        • 参数
        • 交互式界面操作
        • 使用示例
      • perf record
      • 指令格式
        • 参数
        • 使用示例
      • perf report
        • 指令格式
        • 参数
        • 交互式界面操作
        • 使用示例
      • perf diff
        • 命令格式
        • 参数
        • 使用示例
        • 输出字段说明
      • perf script
        • 指令格式
        • 参数
        • 使用示例
        • 输出字段说明
  • 3. 火焰图
    • 3.1 火焰图生成原理
    • 3.2 生成火焰图步骤
      • 1. 安装依赖工具
      • 2. 使用perf record记录性能数据
      • 3. 导出数据为文本格式
      • 4. 生成火焰图
  • 参考内容

1. What is perf?

perf是Linux系统中的一个性能分析工具,它基于事件采样原理,以性能事件为基础,支持针对处理器相关性能指标与操作系统相关性能指标的性能剖析,常用于性能瓶颈的查找和热点代码的定位。

基本原理:对被检测对象进行采样,最简单的是根据tick中断进行采样,即在tick中断内触发采样点,在采样点中判断程序当时的上下文。
事件主要有以下三种:

  • Hardware Event : 是由PMU硬件产生的事件,比如cache命中。当需要了解程序对硬件特性的使用情况时,需要对这些事件进行采样;
  • Software Event : 是内核软件产生的事件,比如进程切换、tick数等;
  • Tracepoint Event : 是内核中的静态tracepoint所触发的事件,这些tracepoint用于判断程序运行期间内核的行为细节,比如slab分配器的分配次数等。

P.S. CPU周期是默认的性能事件。

2. perf使用

2.1 perf的子工具集

1    annotate        解析perf record生成的perf.data文件,显示被注释的代码2    archive         根据数据文件记录的build-id,将所有被采样到的elf文件打包,利用此压缩包,可以在任何机器上分析数据文件中记录的采样数据3    bench           perf中内置的benchmark,目前包含两套针对调度器和内存管理子系统的benchmark4    buildid-cache   管理perf的buildid缓存,每个elf文件都有一个独一无二的buildid,perf用buildid来关联性能数据与elf文件5    buildid-list    列出数据文件中记录的所有buildid6    diff            对比两个数据文件的差异,能够给出每个符号(即函数)在热点分析上的具体差异7    evlist          列出数据文件perf.data中所有性能事件8    inject          该工具读取perf record工具记录的事件流,并将其定向到标准输出,在被分析代码中的任何一点,都可以向事件流中注入其他事件9    kmem            针对内核内存(slab)子系统进行追踪测量的工具10   kvm             用来追踪测试运行在kvm虚拟机上的guest OS11   list            列出当前系统支持的所有性能事件,包括硬件性能事件、软件性能事件,以及检查点12   lock            分析内核中的锁信息,包括锁的竞争情况、等待延迟等13   mem             内存存取情况14   record          收集采样信息,并将其记录在数据文件中,随后可通过其他工具对数据文件进行分析15   report          读取perf record创建的数据文件,并给出热点分析结果16   sched           针对调度器子系统的分析工具17   script          执行perf或python编写的功能扩展脚本、生成脚本框架、读取数据文件中的数据信息等18   stat            执行某个命令,收集特定进程的性能概况,包括CPI、cache不命中率等19   test            perf对当前软硬件平台进行健全性测试,可用此工具测试当前的软硬件平台是否能支持perf的所有功能20   timechart       针对测试期间系统行为进行可视化的工具21   top             类似linux中的top命令,对系统性能进行实时分析22   trace           关于syscall的工具23   probe           用于定义动态检查点

2.2 常用指令

perf list

指令格式
perf list [options] [event_category]
参数
--no-desc : 仅列出事件名称,不显示描述信息
--debug : 显示调试信息,如事件解析过程
--details : 显示事件的详细元数据(如PMU配置)
-j : json格式输出列表
-v : 显示冗余信息,如事件来源
perf中事件分类
  • 硬件事件 Hardware Events:由cpu性能监控单元(PMU)直接提供的底层硬件事件
    • cycles :cpu时钟周期数
    • instructions :执行的指令数
    • cache-misses:缓存失效次数
    • branch-misses:分支预测失败次数
  • 软件事件Software Events:由内核通过软件模拟的事件
    • cpu-clock:cpu时钟时间
    • task-clock:任务占用cpu时间
    • context-switches:上下文切换次数
    • page-faults:缺页异常次数
  • 内核PMU事件 Kernel PMU Events:特定于内核性能监控单元的事件,通常和cpu微架构有关
    • ref-cycles:不受频率调整影响的参考周期数(用于稳定性测试)
    • stalled-cycles-frontend:前端流水线停滞周期数
  • 跟踪点事件Tracepoint Events:静态内核跟踪点(static tracepoints),用于监控内核行为
    • 格式为tracepoint:<子系统>/<事件名>,例如:
      • sched:sched_switch:进程切换事件
        • block:block_rq_issue:块设备I/O请求事件
  • 动态探针事件 Dynamic Tracing:通过perf probe动态插入的探针事件
    • 格式为probe:<函数名>probe:<模块>:<函数名>,例如:
      • probe:vfs_read:监控虚拟文件系统的vfs_read函数
      • probe:libc:malloc:监控libc库的malloc函数
  • 用户空间事件 User Events:用户程序通过pref_event_open接口注册的自定义事件(需代码集成)
  • 其他事件
    • Breakpoint Events:硬件断点事件,如内存访问断点
    • Power Events:电源管理相关事件,如power、energy-cores
使用示例
perf list # 列出所有事件# 按类别过滤事件
perf list hw # 仅列出硬件事件
perf list sw # 仅列出软件的事件
perf list tracepoint # 仅列出跟踪点事件
perf list pmu # 列出pmu事件
perf list probe # 列出动态探针事件# 搜索特定事件
perf list 'sched:*' # 列出调度子系统所有跟踪点事件
perf list 'blokc:*' # 列出块设备相关事件
perf list 'mem:*' # 列出内存相关事件
perf list 'cache-misses' # 搜索包含'cache-misses'的事件

perf stat

指令格式

perf stat 可以查看程序的运行情况,执行该命令时收集性能统计信息.
命令结构:

perf stat [options] <command> # 监控指定指令的执行过程
perf stat [options] -p <pid> # 监控指定进程
perf stat [options] -a # 全局监控所有CPU
perf stat [options] -- <command> # 避免参数冲突时使用“--”分隔
参数
# ---------- 基础控制参数 ---------
-e <event> : 指定监控的事件,多个事件采用逗号分隔
-a : 监控所有CPU核心
-p <pid> : 监控指定进程的实时事件
-C <cpu-list> : 监控指定cpu,示例:-C 0,2    监控cpu0和2
-r <n> : 重复运行命令n次并计算平均值
-o <file> : 将结果保存到文件
--interval-print <ms> : 每隔ms毫秒就输出一次统计# ----------- 事件分组 -------------
-G <group> : 将事件分组统计。例如-G cache,统计所有缓存事件
--per-core : 按cpu核心分组显示结果
--per-socket : 按cpu插槽(物理cpu)分组显示结果# ---------- 输出控制 -------------
-d : 显示详细事件,包括L1/L2/L3缓存、TLB等
-B : 以更紧凑的格式输出(适合脚本解析)
--verbose : 显示调试信息,比如事件解析细节
--no-aggr : 不聚合所有cpu的统计,按核心单独显示
--pre <cmd> : 在监控前执行指定命令,如初始化环境
--post <cmd> : 在监控后执行执行命令,如清理环境# ---------- 高级统计 ----------------
--metric-only : 仅显示指标, 如IPC、缓存命中率等
--pre-thread : 按线程统计事件,需要指定-p <pid>
--scale : 自动缩放数值单位,K/M/G
--timeout <ms> : 监控超时时间,单位ms

关于事件定义:

# 事件语法
-e <event>[:modifiers] # 事件名 + 可选修饰符# 事件类型
硬件事件:cycles,cache-misses等
软件事件:cpu-clock,page-faults等
内核PMU事件:ref-cycles
自定义事件:perf list查看所有支持的事件# 修饰符
u : 仅监控用户空间事件
k : 仅监控内核空间事件
h : 仅监控Hypervisor事件
G : 全局事件(跨进程共享)
H : 主机端事件(虚拟化环境)# 示例:
perf stat -e cycles,instructions,cache-misses:u ./result.out # 监控用户空间的缓存失效

perf top

指令格式
perf top [options]
参数
# ------ 基础控制参数 -------
-e <event> # 指定监控的事件,默认为cycles
-p <pid> # 监控指定进程
-C <cpu-list> # 监控指定cpu
-K # 隐藏内核空间符号(仅显示用户空间函数)
-U # 隐藏用户空间符合,仅显示内核空间函数
--no-children # 不显示子函数调用占比
--call-graph <type> # 设置调用图类型(fp:帧指针;dwarf:调试信息;lbr:硬件记录)
-F <频率> # 设置采样频率;例如 -F 100表示每秒采样100次
-g # 记录调用链(生成火焰图时常用)# -------- 输出控制 -----------
-d <s> # 界面刷新间隔,默认2s
-n # 显示样本数量,不是百分比
--stdio # 非交互模式,直接输出到终端
--sort <字段> # 按照字段排序,例如symbol、overhead
--fields <字段> # 自定义显示字段,例如symbol、overhead
--percent-limit <数值> # 仅显示占比超过指定百分比的事件,例如 --percent-limit 0.5# -------- 高级分析 -----------
--branch-history # 显示历史分支(需要CPU支持LBR)
--demangle-kernel # 解析内核符号名称,显示可读函数名
--objdump <path> # 指定反汇编工具路径(用于汇编代码分析)
交互式界面操作

在perf top的实时界面中,支持以下快捷键:

h : 显示帮助菜单
q : 退出
Enter : 选中符号,查看其调用链详情
E : 展开所有调用链
C : 折叠所有调用链
+/- : 调整符号显示的百分比阈值
k : 显示内核符号
u : 显示用户空间符号
z : 高亮当前选中的符号
使用示例
perf top -p <pid> # 按照pid监控指定进程的热点函数
perf top -e cache-missed # 实时显示缓存失效最多的函数
perf top -g --call-graph dwarf # 记录调用链,生成火焰图时使用# 生成火焰图

perf top回显字段含义说明:

overhead : 事件占比(百分比)
Shared Object : 所属模块,如[kernel],[libc.so.6]
Symbol : 函数或符号名称
Dso : 动态共享对象(模块或程序名)

![[Pasted image 20250420191525.png]]

perf record

指令格式

perf record [options] <command> # 记录命令执行期间的性能数据
perf record [options] -p <pid> # 记录指定进程的性能数据
perf record [options] -a # 全局记录所有cpu的性能数据
参数
# --------- 基础控制参数 ------------
-e <event> # 指定监控的事件
-F <频率> # 设置采样频率
-g # 记录调用链,生成火焰图必备
-p <pid> # 监控指定进程
-a # 全局监控所有cpu
-C <cpu-list> # 监控指定cpu
-o <file> # 输出文件名,默认perf.data
--call-graph <type> # 调用链记录方式:fp/dwarf/lbr# --------- 事件与过滤 -------------
-c <次数> # 每发生n次事件采样一次。替代-F,比如-c 100
--filter <filter> # 事件过滤器,如监控特定地址范围
-b # 启用分支栈采样(需cpu支持)# ----------- 输出与调试 -------------
-v # 显示详细信息
-s # 按线程单独记录样本
-k <时钟> # 指定时钟源,如mono/monotonic_raw
--timestamp # 记录时间戳
--switch-events # 记录上下文切换事件# ----------- 其他 ----------
--pid-map <file> # 指定pid映射文件(容器环境)
--namespaces # 记录命名空间信息
--aux # 启用aux区域跟踪(用于Intel PT)
--tail-synthesize # 在记录结束时合成事件
使用示例
perf record -F 100 ./my_proj # 记录命令my_proj的cycles事件,采样频率为100
perf record -g --call-graph dwarf ./my_proj # 记录调用链,使用dwarf调试信息
perf record -e cache-misses -p 311 # 监控pid为311的进程,采样缓存失效事件
perf record -e instrutions -a # 全局监控所有cpu的指令数事件
perf record -o mydata.data ./my_proj # 将记录保存到mydata.data文件中

perf report

指令格式
perf report [options] # 分析perf.data(默认文件名)
perf report -i <file> # 分析指定文件
参数
# ----------- 输入控制参数 --------------
-i <file> # 指定输入文件,默认是perf.data
--force # 强制读取文件,忽略版本不兼容警告
--kallsyms <path> # 指定内核符号表路径,默认为/proc/kallsyms
--vmlinux <path> # 指定内核调试符号文件,解析内核符号# ------- 输出控制参数 -------------
--stdio # 命令行模式输出(非交互式)
--tui # 启用交互式文本界面(默认)
--gtk # 使用GTK图形界面(需要编译支持)
--header # 显示文件头信息(事件、命令行等)
--sort <字段> # 按字段排序(如pid,comm,dso等)
--fields <字段> # 自定义显示字段(如overhead,symbol)
--percent-limit <数值> # 仅显示占比超过指定百分比的事件# ------=----- 分析模式 ----------------
-g <type> # 生成调用链(graph、callee或none)
--branch-history # 显示分支历史(需记录分支数据)
--objdump <path> # 指定反汇编工具路径(查看汇编代码)
--demangle # 解析C++符号名称
--source # 显示源码与汇编代码(需调试信息)# ------------- 过滤与统计 ----------
-C <cpu> # 仅显示指定cpu的样本
-p <pid> # 仅显示指定进程的样本
-s <字段> # 按字段聚合统计(如symbol或dso)
--filter <规则> # 过滤样本(比如comm="my_program")
交互式界面操作

perf report 的 TUI界面中,支持以下快捷键:

Enter : 展开选中符号的调用链
ESC : 返回上一级调用链
h : 显示帮助菜单
q : 退出
E : 展开所有调用链
C : 折叠所有调用链
+/- : 调整显示的百分比阈值
a : 显示注解(注释热点代码)
d : 过滤当前符号
t : 切换显示模式(百分比/样本数)
/ : 搜索符号或模块名
使用示例
perf report # 默认分析perf.data
perf report --stdio # 非交互式输出(适合脚本处理)
perf report -C 0,1 # 仅显示cpu 0和1的样本
perf report --sort symbol #  按符号名聚合统计
perf report -g graph # 显示函数调用链
perf report --source # 显示源码与汇编代码(需编译时保留调试信息)

perf diff

perf diff用于比较两个或多个perf.data文件的性能分析结果,帮助开发者快速识别优化前后的性能差异。

核心功能

  • 对比性能数据:比较不同运行场景下的事件统计,如cpu周期、缓存命中率等
  • 识别热点变化:找出函数或代码路径的性能改进或退化
  • 多文件支持:支持同时对比多个数据文件(如基线版本和优化版本)

使用步骤

  1. 生成基准数据
    perf record -o perf.data.base -- ./my_program_base # 生成基准数据perf.data.base
    
  2. 生成对比数据
    perf record -o perf.data.optimized -- ./my_program_optimized # 生成优化后的数据perf.data.optimized
    
  3. 执行对比
    perf diff perf.data.base perf.data.optimized
    
命令格式
perf diff [options] <file1> <file2> ... # 对比多个文件
perf diff [options] # 对比当前目录的perf.data文件
参数
-b 或 --baseline <file> # 指定基准文件,默认第一个文件为基准
-c 或 --compute <方式> # 差异计算方式:delta/ratio/wdiff,默认为delta
-q 或 --quiet # 仅显示显著差异,隐藏无变化的条目
-m 或 --modules # 按模块(动态库/内核模块)聚合差异
-s 或 --sort <字段> # 按字段排序,如delta/ratio/overhead
--percent-limit <数值> # 仅显示差异超过指定百分比的事件
-C 或 --cpu <cpu> # 仅对比指定cpu的样本
-p 或 --pid <pid> # 仅对比指定进程的样本
使用示例
perf diff -b perf.data.base perf.data.optimized # 指定基准文件
perf diff -s delta perf.data.base perf.data.optimized # 按差异百分比排序
perf diff --percent-limit 5.0 # 仅显示差异超过5%的条目
perf diff perf.data.v1 perf.data.v2 perf.data.v3 # 对比多组数据
输出字段说明
Overhead : 差异的百分比,正值为性能退化,负值为优化
Baseline : 基准文件的样本数或事件计数
Comparison : 对比文件的样本数或事件计数
Delta : 绝对值差异(对比文件 - 基准文件)
Symbol : 函数或符号名称

perf script

perf script的核心功能:

  • 数据导出:将perf.data中的性能数据(如采样事件、调用链、时间戳等)转换为可读文本;
  • 灵活过滤:按进程、CPU、时间范围等条件筛选数据;
  • 自定义输出:指定输出的字段格式(如csv、json),方便后续处理
  • 脚本扩展:结合perl或python脚本实现自动化分析
指令格式
perf script [options] # 默认读取perf.data
perf script -i <file> # 指定输入文件
参数
-i <file> # 指定输入文件
-F <字段> # 自定义输出字段(如time、event等)
-S <脚本> # 使用perl或python脚本解析数据
-f <格式> # 指定输出格式
--ns # 显示纳秒级时间戳
-C <cpu> # 仅显示指定cpu的样本
-p <pid> # 仅显示指定进程的样本
--time <start, end> # 按时间范围过滤样本(单位为秒)
-k <vmlinux> # 指定内核符号文件
-g # 显示调用链
--demangle # 解析C++符号名
--header # 显示文件头信息(事件类型、命令行等)
使用示例
perf script > output.txt # 导出所有数据为文本
perf script flamegraph.pl > flame.svg # 生成火焰图数据
perf script -g # 显示每个样本的完整调用链
输出字段说明
COMM : 进程名
PID : 进程id
TID : 线程id
TIME : 时间戳s
EVENT : 事件类型,如cycles
IP : 指令指针地址
SYM : 符号(函数名)
DSO : 动态共享对象(模块或程序名)

3. 火焰图

火焰图是一种用户可视化程序性能分析数据的工具。它的核心原理是通过采样捕获程序运行时的函数调用栈,并将这些调用栈按层级聚合,最终以直观的图形展示cpu时间的分布

3.1 火焰图生成原理

  1. 采样
    • perf以固定频率中断程序运行,记录当前的函数调用栈;
    • 每个样本包含从底层函数到当前执行点(如某个具体函数)的完整调用链
  2. 聚合与折叠
    • 将大量样本按调用栈的层级结构合并统计,相同的调用路径会合并为一个条目;
    • e.g. 函数A调用函数B,函数B调用函数C,则这个三个函数的调用链会被合并统计
  3. 可视化
    • 将聚合后的数据转换为svg图像,每个矩形代表一个函数:
      • 宽度:表示该函数在采样中的出现频率,即cpu时间占比
      • 层级:火焰图的层级结构

3.2 生成火焰图步骤

1. 安装依赖工具

克隆FlameGraph工具库:

git clone https://github.com/brendangregg/FlameGraph.git

2. 使用perf record记录性能数据

注意要加-g参数:

perf record -F 99 -g -- <command> #
# 示例
perf record -F 99 -a -g -- sleep 30 # 监控所有cpu的cycles事件30s

3. 导出数据为文本格式

将perf.data转换为可处理的文本;

perf script > output.perf

4. 生成火焰图

使用flamegraph工具链处理数据:

# 折叠调用栈(统计相同路径)
stackcollapse-perf.pl < output.perf > output.folded
# 生成svg火焰图
flamegraph.pl output.folded > flamegraph.svg# 命令简化,一步完成
perf script | stackcollapse-perf.pl | flamegraph.pl > flamegraph.svg

参考内容

  • Linux 性能分析工具perf使用 - -零 - 博客园
  • 从小白到精通:揭秘perf工具的全部功能与操作技巧-CSDN博客

相关文章:

  • 基于 OpenCV 的图像与视频处理
  • Kubernetes(k8s)学习笔记(二)--k8s 集群安装
  • React+TS编写轮播图
  • 计算机视觉cv入门之Haarcascade的基本使用方法(人脸识别为例)
  • 【后端】【Django】Django 模型中的 `clean()` 方法详解:数据校验的最后防线
  • 【人工智能】推荐开源企业级OCR大模型InternVL3
  • css3新特性第四章(渐变)
  • 【条形码识别改名工具】如何批量识别图片条形码,并以条码内容批量重命名,基于WPF和Zxing的开发总结
  • 【iOS】alloc init new底层原理
  • 嵌入式---零点漂移(Zero Drift)
  • 网络设备基础运维全攻略:华为/思科核心操作与巡检指南
  • IDEA多环节实现优雅配置
  • IDEA在Git提交时添加.ignore忽略文件,解决为什么Git中有时候使用.gitignore也无法忽略一些文件
  • 国际数据加密算法(IDEA)详解
  • 按字符串长度升序,长度相同则按字典序
  • 【Linux系统】Linux基础指令(详解Linux命令行常用指令,每一个指令都有示例演示)
  • 30天开发操作系统 第26天 -- 为窗口移动提速
  • 实现AWS Data Pipeline安全地请求企业内部API返回数据
  • 2026《数据结构》考研复习笔记四(第一章)
  • 蓝桥杯 二进制问题 刷题笔记
  • 韩国一战机飞行训练中掉落机炮吊舱和空油箱
  • 纪念沈渭滨︱志于道而游曳于士和氓间的晚年沈先生
  • 观察|美军在菲律宾部署新导弹,试图继续构建“导弹链”
  • 江西一季度GDP为7927.1亿元,同比增长5.7%
  • 英国称担忧中国无人机拍摄英国重要基建高清图像,外交部回应
  • 2月美国三大债主均增持美国国债,中国增持235亿美元