Perf 工具与火焰图使用指南

136 阅读6分钟

Perf 工具与火焰图使用指南

参考资料


目录


一、Perf 工具介绍

perf 命令(performance 的缩写),是 Linux 系统提供的性能分析工具集,包含多种子工具,能够监测多种硬件及软件性能指标,包括 CPU、内存、IO 等,这些可监测指标我们称为 Event

graph LR
    A[Perf 工具] --> B[Hardware Event]
    A --> C[Software Event]
    A --> D[Tracepoint Event]
    B --> B1[CPU 周期]
    B --> B2[Cache 缺失]
    B --> B3[分支预测]
    C --> C1[上下文切换]
    C --> C2[缺页异常]
    C --> C3[系统调用]
    D --> D1[内核跟踪点]
    D --> D2[Slab 分配]

二、Perf 工作模式

2.1 计数模式

记录 perf 执行过程中 event 的出现次数。

2.2 采样模式

在 perf 执行过程中,按照指定频率去采样 event,每次采样时,记录当前性能指标信息(CPU、进程 ID、运行栈等)。

⚠️ 注意:这种方式由于每次都记录信息,所以额外的资源消耗是比较大的,需要权衡采样频率。

flowchart TB
    subgraph 计数模式
        A1[开始监控] --> A2[统计 Event 次数] --> A3[输出统计结果]
    end
    subgraph 采样模式
        B1[开始监控] --> B2[按频率采样] --> B3[记录详细信息] --> B4[生成数据文件]
    end

三、Perf 安装

3.1 通过包管理器安装(Ubuntu)

对于 Ubuntu 等 Linux 系统发行版,都提供了对应的包,只要根据内核版本进行安装即可:

# 在 Ubuntu 下安装
sudo apt-get install linux-tools-common
sudo apt-get install linux-tools-"$(uname -r)"
sudo apt-get install linux-cloud-tools-"$(uname -r)"
sudo apt-get install linux-tools-generic
sudo apt-get install linux-cloud-tools-generic

💡 提示:Linux 系统可能无法找到和 kernel 版本相同的工具安装包,可以使用其他版本替换。

如果版本不匹配,可以手动创建软链接:

sudo rm /usr/bin/perf
sudo ln -s /usr/lib/linux-tools-4.15.0-163/perf /usr/local/bin/perf

3.2 从源码编译安装(推荐)

⚠️ 重要提示:不能直接 make,需要先安装某些依赖,否则会导致某些异常。缺少某些库请参照编译的提示进行安装。

内核资源

编译步骤

# 1. 下载源码
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

# 2. 切换至对应的版本分支
cd linux
git branch -r      # 查看所有远程分支
git branch -a      # 查看所有分支
git checkout v5.4  # 切换到 v5.4 分支

# 3. 编译安装 perf
cd tools/perf
make

# 4. 测试 perf 是否成功安装
cd ../..
sudo perf top
flowchart LR
    A[下载源码] --> B[切换版本分支]
    B --> C[进入 tools/perf]
    C --> D[执行 make]
    D --> E[验证安装]

四、Perf 使用方法

4.1 perf list

查看当前系统支持的性能事件。使用 perf list 命令可以显示当前软硬件环境下支持的所有事件:

事件类型说明示例
Hardware Event由 PMU 部件产生,在特定条件下探测性能事件CPU 周期、分支指令、TLB 重填例外、Cache 缺失
Software Event内核产生的事件,统计操作系统相关性能事件系统调用次数、上下文切换次数、任务迁移次数、缺页例外次数
Tracepoint Event内核中静态 tracepoint 触发的事件slab 分配器的分配次数等

4.2 perf top

类似 top 命令,主要用于实时分析各个函数在某个性能事件上的热度,能够快速定位热点函数,包括应用程序函数、模块函数与内核函数,甚至能够定位到热点指令。

🔐 执行需要 root 权限

常用参数

参数说明
-e <event>指明要分析的性能事件
-p <pid>仅分析目标进程及其创建的线程

4.3 perf stat

用于统计 event 出现的次数(计数模式)。

默认事件说明

事件名称说明
cpu-clock任务真正占用的处理器时间(ms)。CPUs utilized = cpu-clock / time elapsed,值高说明程序多数时间花费在 CPU 计算上而非 IO
context-switches上下文的切换次数
CPU-migrations处理器迁移次数。Linux 为维持多处理器负载均衡,会将任务从一个 CPU 迁移到另一个 CPU
page-faults缺页异常次数。页面未建立、不在内存、映射关系未建立、TLB 不命中、权限不匹配等都会触发
cycles消耗的处理器周期数
instructions执行的指令数。IPC 为平均每个 CPU cycle 执行的指令数
branches遇到的分支指令数
branch-misses预测错误的分支指令数

参数说明

-e <event>  # 指定性能事件(可以是多个,用 , 分隔)
-p <pid>    # 指定待分析进程的 pid(可以是多个,用 , 分隔)
-t <tid>    # 指定待分析线程的 tid(可以是多个,用 , 分隔)
-a          # 从所有 CPU 收集系统数据
-d          # 打印更详细的信息,可重复 3 次
            #   -d:L1 和 LLC data cache
            #   -d -d:dTLB 和 iTLB events
            #   -d -d -d:增加 prefetch events

4.4 perf record

采样模式,perf 收集采样信息并记录在文件中,可以离线分析。使用 perf report 解析收集的采样数据文件。

参数说明

参数说明
-e选择性能事件
-p待分析进程的 id
-t待分析线程的 id
-a分析整个系统的性能
-C只采集指定 CPU 数据
-F采样频率,每秒多少次
-c事件的采样周期
-o指定输出文件,默认为 perf.data
-A以 append 的方式写输出文件
-f以 OverWrite 的方式写输出文件
-g记录函数间的调用关系

使用示例

sudo perf record -e cpu-clock -g -p 2548
# -g         告诉 perf record 额外记录函数的调用关系
# -e cpu-clock  监控的指标为 cpu 周期 
# -p         指定需要 record 的进程 pid

💡 采样一段时间后,可以使用 Ctrl+C 停止命令,这时会生成 perf.data 文件(默认文件名)

4.5 perf report

主要用来分析 perf record 生成的 perf.data 文件。


五、生成火焰图

5.1 操作流程

flowchart LR
    A[perf record<br/>采集数据] --> B[perf script<br/>导出文本]
    B --> C[stackcollapse-perf.pl<br/>折叠堆栈]
    C --> D[flamegraph.pl<br/>生成 SVG]
    D --> E[浏览器查看<br/>火焰图]

5.2 第一步:采样并记录性能数据

# 对 CPU 所有进程 99Hz 采集,执行 60 秒后采集完成,当前目录生成 perf.data 文件
perf record -F 99 -a -g -- sleep 60
perf script > out.perf

# 或者:对进程 id 181 采集,采集时间 60 秒,执行期间不要退出
perf record -F 99 -p 181 -g -- sleep 60
perf script > out.perf

5.3 第二步:用 FlameGraph 工具解析

工具仓库github.com/brendangreg…

# 克隆工具仓库
git clone https://github.com/brendangregg/FlameGraph.git
cd FlameGraph

# 折叠堆栈信息
./stackcollapse-perf.pl out.perf > out.folded

# 生成火焰图
./flamegraph.pl out.folded > kernel.svg

5.4 解读火焰图

火焰图是基于 stack 信息生成的 SVG 图片,用来展示 CPU 的调用栈。

graph TB
    subgraph 火焰图结构
        direction TB
        Y[Y 轴:调用栈深度<br/>顶部是正在执行的函数<br/>下方是父函数]
        X[X 轴:抽样数/执行时间<br/>宽度越大执行时间越长<br/>按字母顺序排列]
    end

关键要点

元素说明
方框每个方框代表一个函数
宽度方框越宽,代表执行时间越久
高度楼层越高,代表调用栈越深
顶层最顶层的函数是叶子函数(正在执行的函数)
平顶如果有"平顶"(plateaus),表示该函数可能存在性能问题

🎯 分析技巧:火焰图就是看顶层的哪个函数占据的宽度最大。只要有"平顶",就表示该函数可能存在性能问题,是优化的重点目标。


附录:快速参考卡片

# 实时查看热点函数
sudo perf top -p <pid>

# 统计性能事件
sudo perf stat -p <pid> -d

# 采样并生成火焰图(完整流程)
sudo perf record -F 99 -p <pid> -g -- sleep 60
perf script > out.perf
./stackcollapse-perf.pl out.perf > out.folded
./flamegraph.pl out.folded > flame.svg