3. Perf 基本命令:用法与参数详解

在 Android 底层驱动调优中,perf 是最核心的性能剖析工具。本章将系统讲解 perf 的五大基本命令——perf list、perf stat、perf record、perf report、perf top,涵盖其典型用法、关键参数及在驱动场景下的实践要点。掌握这些命令是后续进行中断分析、调度延迟、缓存命中率等专项调优的基础。

前置条件:确保目标 Android 设备内核已开启 CONFIG_PERF_EVENTS,且用户空间包含 perf 工具(通常位于 /system/bin/perf 或通过 adb shell 使用)。对于非 root 设备,部分硬件事件可能需要 perf_event_paranoid 调整为 1 或更低。

3.1 perf list:列出可监控的事件

perf list 用于查询当前内核与硬件支持的所有性能事件,是驱动开发者选择监控目标的起点。

3.1.1 基本用法

# 列出所有事件(硬件、软件、tracepoint、PMU)
adb shell perf list

# 按类别筛选
adb shell perf list hw          # 仅硬件事件
adb shell perf list sw          # 仅软件事件
adb shell perf list cache       # 仅缓存事件
adb shell perf list tracepoint  # 仅内核 tracepoint

3.1.2 驱动调优常用事件

事件类别 典型事件名 驱动调优场景
硬件 (PMU) cpu-cycles, instructions, cache-misses 评估中断处理函数指令效率、DMA 缓存一致性开销
软件 context-switches, page-faults, cpu-migrations 分析驱动线程调度延迟、内存映射开销
Tracepoint irq:irq_handler_entry, sched:sched_wakeup, power:cpu_idle 追踪中断响应时间、唤醒延迟、电源状态切换
动态 PMU exynos-llc, cci (取决于 SoC) 监控片内互联/LLC 延迟,优化驱动缓存一致性协议
注意:不同 SoC(如 Qualcomm、MTK、Exynos)的 PMU 事件名可能不同。务必先在目标设备上执行 perf list 确认可用事件,避免在脚本中硬编码不存在的 PMU 名称。
perf list 事件分类与驱动调优映射 硬件 PMU 事件 cycles, cache-misses 软件事件 cs, pf, migrations Tracepoint irq, sched, power 动态 PMU LLC, CCI, DSU 驱动调优目标 中断延迟 / 调度抖动 / 缓存一致性 / 功耗 💡 驱动开发者应优先关注 tracepoint (irq/sched) 和硬件 cache-misses,它们是定位驱动性能瓶颈的第一入口。

3.2 perf stat:快速统计性能计数器

perf stat 用于在程序或一段命令执行期间,汇总关键性能计数器的总值与平均值,适合快速评估驱动模块的整体开销。

3.2.1 基本语法与驱动示例

# 统计一个驱动测试程序执行期间的硬件事件
adb shell perf stat -e cycles,instructions,cache-misses,branch-misses \
  /data/local/tmp/driver_test

# 统计内核模块加载时的软件事件
adb shell perf stat -e context-switches,page-faults,cpu-migrations \
  -- insmod /vendor/lib/modules/gpu_drv.ko

# 统计特定 PID 驱动线程 5 秒内的统计
adb shell perf stat -p 1234 -e irq:irq_handler_entry,irq:irq_handler_exit sleep 5

3.2.2 关键参数

参数 说明 驱动调优典型用法
-e 指定事件列表,逗号分隔 -e cycles,instructions,cache-misses
-p 监控指定 PID -p $(pidof surfaceflinger) 分析显示驱动
-a 全系统模式 -a -e cache-misses 评估全局缓存压力
-r N 重复运行 N 次,取平均值 -r 5 ./dma_test 消除单次抖动
--per-core 按 CPU 核分别输出统计 分析中断亲和性是否均衡
--interval-print N 每 N 毫秒打印一次快照 观察驱动在不同负载阶段的计数器变化
驱动调优实战:使用 perf stat -e instructions,cycles -p <irq_thread_pid> --interval-print 1000 可以每秒观察中断线程的 IPC(Instructions Per Cycle)。若 IPC 持续低于 0.5,说明该中断处理函数存在严重的指令停顿(如 cache miss 或分支预测失败),需要进一步用 perf record 定位热点。
perf stat 驱动性能统计流程 perf stat 命令 内核 PMU / Tracepoint 硬件计数器 + 软件事件 统计报告 总值 / 平均值 / 标准差 驱动调优决策 IPC 过低 → 定位 cache miss / 分支预测

3.3 perf record & perf report:采样与热点分析

perf record 通过采样(sampling)记录事件发生时 CPU 的指令指针(IP)或调用栈,perf report 则对采样数据进行符号解析与排序,生成热点报告。这是驱动开发者定位性能瓶颈最强大的组合。

3.3.1 典型驱动采样场景

# 场景1:对驱动测试程序进行 CPU 周期采样,生成调用链
adb shell perf record -e cycles -g --call-graph dwarf \
  -o /data/local/tmp/perf.data /data/local/tmp/driver_test

# 场景2:采样特定内核线程(如 IRQ 线程)10 秒
adb shell perf record -e cycles -p $(pidof irq/296-5b10000) \
  -g -- sleep 10

# 场景3:全系统采样 cache-misses,关注驱动模块
adb shell perf record -e cache-misses -a -g -- sleep 5

3.3.2 关键参数对比

参数 perf record perf report
-e 指定采样事件(默认 cycles) 过滤只显示某事件的数据
-g 记录调用栈(call-graph) 显示调用链占比
--call-graph 设置栈展开方式:fp / dwarf / lbr —
-p 附加到指定 PID —
-a 全系统采样 —
-F 采样频率(如 1000 Hz) —
-i — 指定输入文件(默认 perf.data)
--sort — 排序方式:comm, dso, symbol, srcline
--stdio — 以文本形式输出,适合脚本处理

3.3.3 驱动热点分析示例

# 在设备上生成采样数据后,拉取到主机分析
adb pull /data/local/tmp/perf.data .
perf report -i perf.data --sort comm,dso,symbol --stdio | head -40

# 输出示例(驱动相关):
# # Overhead  Command          Shared Object          Symbol
# # ........  ...............  .....................  ......................
#     35.20%  irq/296-5b10000  [kernel.kallsyms]     [k] dma_alloc_from_pool
#     12.15%  irq/296-5b10000  [kernel.kallsyms]     [k] _raw_spin_lock_irqsave
#      8.70%  irq/296-5b10000  [vendor_module.ko]    [k] gpu_irq_handler
驱动调优要点:若热点集中在 dma_alloc_from_pool 或 _raw_spin_lock_irqsave,说明驱动在中断上下文中频繁进行内存分配或自旋锁竞争。优化方向包括:使用预分配 DMA 池、改用无锁数据结构、将耗时操作推迟到工作队列。
perf record → perf report 驱动热点分析流程 perf record 采样 cycles / cache-misses perf.data 采样 IP + 调用栈 perf report 符号解析 + 排序 热点输出示例(驱动视角) 35.2% irq/296-5b10000 [kernel.kallsyms] dma_alloc_from_pool 12.1% irq/296-5b10000 [kernel.kallsyms] _raw_spin_lock_irqsave 8.7% irq/296-5b10000 [vendor_module.ko] gpu_irq_handler

3.4 perf top:实时热点监控

perf top 类似于 Linux top 命令,但展示的是实时采样中最耗 CPU 的函数(符号)排名,适合在驱动运行过程中动态观察热点变化。

3.4.1 驱动实时监控命令

# 实时显示内核与用户空间热点(默认采样 cycles)
adb shell perf top

# 只显示内核态符号(驱动模块通常在内核态)
adb shell perf top -k vmlinux --kallsyms /proc/kallsyms

# 按特定事件排序(如 cache-misses)
adb shell perf top -e cache-misses -a

# 显示调用链(-g),帮助理解热点上下文
adb shell perf top -g -p $(pidof surfaceflinger)

3.4.2 常用参数

参数 说明 驱动场景
-e 指定采样事件 -e cache-misses 观察缓存未命中热点
-p 只监控指定 PID -p $(pidof irq/xxx) 聚焦中断线程
-K 不显示用户空间符号 只关注内核驱动模块
-U 不显示内核空间符号 分析用户态驱动 HAL 层
-n 显示采样计数 评估热点函数的绝对采样频率
--sort 排序方式(默认按 overhead) --sort dso,symbol 按模块分组
性能开销注意:perf top 默认以 1000 Hz 频率采样,在低端 Android 设备上可能引入 1-3% 的额外开销。对于生产环境或功耗敏感测试,建议降低采样频率(-F 100)或使用 perf record 离线分析。
perf top 实时驱动热点监控 perf top 进程 PMU 中断采样 每 N 个周期触发 符号解析 kallsyms / debuginfo TUI perf top 实时输出(驱动模块示例) 28.5% [kernel] [k] dma_alloc_from_pool 15.2% [vendor] [k] gpu_irq_handler 10.8% [kernel] [k] _raw_spin_lock_irqsave

3.5 命令选择矩阵

根据不同的驱动调优阶段,选择合适的 perf 命令可以事半功倍:

调优阶段 推荐命令 核心关注点
事件探索 perf list 确认目标 SoC 支持的 PMU 与 tracepoint
快速评估 perf stat IPC、cache-miss 率、上下文切换频率
热点定位 perf record + report 函数级热点、调用链、锁竞争
实时监控 perf top 动态观察热点变化,验证优化效果
驱动调优工作流建议:先 perf list 确认可用事件 → perf stat 快速评估整体指标 → 若发现异常(如 cache-miss 率 > 10%),使用 perf record -g 采样并生成报告 → 根据热点函数优化代码 → 用 perf top 实时验证优化效果。此闭环可高效迭代驱动性能。