Simpleperf 工具的介绍与使用

2,190 阅读3分钟

一、Simpleperf 介绍

Simpleperf 是一个通用的命令行 CPU 性能剖析工具,包含在面向 Mac、Linux 和 Windows 的 NDK 中。详细内容请参看官方文档,本文的第一部分主要来自源码中 simpleperf 的介绍 PPT

概览
源码位置android.googlesource.com/platform/sy…
适用进程android 进程/native 进程
适用语言JAVA/C++
执行程序要求>= L
python 脚本要求>= N
组成linux kernel 支持 + PMU(performance monitor unit) 硬件支持

下载工具:

$ git clone https://android.googlesource.com/platform/system/extras ~/extras
$ cd ~/extras/simpleperf/scripts

1.1 simpleperf 工作原理

图片.png

1.2 ARM PMU

  • ARM 手册中有介绍,D7 性能监测扩展
  • PMU 计数器:每个 cpu 核有若干个 PMU 计数器。每个计数器占 32-bit,可以监测一个 PMU 事件。当被监测的事件发生时,计数器的值就加1。当一个计数器溢出时,它会触发一次中断。
  • PMU 事件:像 CPU_CYCLES,BR_PRED(预测的分支),L1D_CACHE(1级数据缓存访问)等。ARM 展示通用的事件以及如何中断它们。并且时间可以用来获取间接的信息,像缓存命中率 = 缓存计数重填计数 / 缓存访问计数。
  • 一般新架构中会新增更多 PMU 事件。

1.3 kernel 支持

perf 事件驱动

  • 作为用户空间和 pmu 驱动之间的桥梁,位于 kernel/events
  • 将 pmu 事件映射到 perf 事件类型,位于 include/uapi/linux/perf_event.h
  • 提供sysfs 接口显示支持的 perf 事件,位于 /sys/bus/event_source
  • 提供 perf_event_open 系统调用监测选中的线程性能

图片.png

pmu 驱动

  • 通过 perf_pmu_register() 注册 perf 事件驱动。
  • cpu pmu 驱动,操作 ARM PMU,位于 drivers/perf。
  • 软件 pmu 驱动,像 cpu 时钟、页错误事件,完整列表位于 perf_sw_ids。
  • 跟踪点 pmu 驱动,像 sched:sched_switch 事件,完整列表位于 /sys/kernel/tracing/events。
  • 设备指定 pmu 驱动。

二、 simpleperf 指令

  • simpleperf 是一个运行在设备上的可执行文件,位于 /system/bin。
  • simpleperf 将其功能划分到子命令中。
    • list 指令:展示设备上可用的 perf 事件
    • stat 指令:监测线程,并打印 perf 事件计数器的值
    • record 指令:监测线程,并生成采样的分析数据
    • report 指令:汇报由 record 指令生成的分析数据
  • simpleperf 也提供运行在主机上的 python 脚本
    • 帮助 record
    • 帮助 report

list 指令:展示可用的事件

$ simpleperf list                                                                                           
List of hw-cache events:
  # More cache events are available in `simpleperf list raw`.
  branch-load-misses
  branch-loads
  dTLB-load-misses
  dTLB-loads
  iTLB-load-misses
  iTLB-loads
  L1-dcache-load-misses
  L1-dcache-loads
  L1-icache-load-misses
  L1-icache-loads
  LLC-load-misses
  LLC-loads

List of coresight etm events:

List of hardware events:
  branch-misses
  bus-cycles
  cache-misses
...

stat 指令:获取 perf 事件计数器的值

图片.png

stat 指令:选项

simpleperf stat -h                                                                                        
Usage: simpleperf stat [options] [command [command-args]]
       Gather performance counter information of running [command].

选项:
-p pid1,pid2,... Stat events on existing processes.
-t tid1,tid2,... Stat events on existing threads. 
-a           Collect system-wide information.
--cpu cpu_item1,cpu_item2,...
                 Collect information only on the selected cpus. cpu_item can
-e event1[:modifier1],event2[:modifier2],...
                 Select a list of events to count. 
 --duration time_in_sec  Monitor for time_in_sec seconds instead of running
                        [command].                

stat 指令:例子

# simpleperf stat -e cache-references,cache-misses -a --duration 1
Performance counter statistics:

#      count  event_name         # count / runtime,  runtime / enabled_time
  34,724,046  cache-references   # 4.306 M/sec          (100%)
     620,325  cache-misses       # 1.786442% miss rate  (100%)

Total test time: 1.001952 seconds.

record 指令:生成采样的分析数据

图片.png

record 指令:选项

# simpleperf record -h                                                                                          
Usage: simpleperf record [options] [--] [command [command-args]]
       Gather sampling information of running [command].
       
选项:
-p pid1,pid2,...       Record events on existing processes. 
-t tid1,tid2,... Record events on existing threads.
-a     System-wide collection.
--cpu cpu_item1,cpu_item2,...
             Collect samples only on the selected cpus.
-e event1[:modifier1],event2[:modifier2],...
             Select a list of events to record.
-f freq      Set event sample frequency.It means recording at most [freq]
             samples every second.
--duration time_in_sec  Monitor for time_in_sec seconds
-o record_file_name    Set record file name, default is perf.data.
-g           Same as '--call-graph dwarf'.

record 指令:例子

$ simpleperf record -g sleep 1

simpleperf I cmd_record.cpp:696] Recorded for 1.01908 seconds. Start post processing.
simpleperf I cmd_record.cpp:771] Samples recorded: 56. Samples lost: 0.

record 指令:采样格式

分析数据包含一个采样列表。 每个采样可以包含以下信息(完整列表在此):

time      - CLOCK_MONOTONIC 中的时间戳
pid,tid   - 进程 id,线程id
cpu       - cpu
period    - 自上次采样后发生了多少事件
ips[]     - 调用栈(基于调用栈的栈帧指针)
regs[]    - 用户空间寄存器值
stack[]   - 用户栈数据最多 64kb

基于 dwarf 的调用栈是由堆栈展开生成

report 指令:汇报分析数据

$ simpleperf report

Cmdline: /system/bin/simpleperf record -g sleep 1
Arch: arm64
Event: cpu-cycles (type 0, config 0)
Samples: 56
Event count: 13885436

Overhead Command   Pid   Tid    Shared Object        Symbol
9.61%    sleep    14852 14852 [kernel.kallsyms]     vma_link
8.97%    sleep    14852 14852 linker64              soinfo_do_lookup_impl
6.42%    sleep    14852 14852 linker64              BionicAllocator::alloc_impl
6.11%    sleep    14852 14852 [kernel.kallsyms]     __follow_mount_rcu
5.83%    sleep    14852 14852 [kernel.kallsyms]     clear_page

在主机上汇报分析数据

将记录文件拉到主机上并使用多汇报方法(脚本位置在此

二、工具使用

虽然 simpleperf 既有设备上的可执行文件也有 python 脚本,但相对来说 python 脚本使用更便捷。

Python 脚本使用

脚本路径:/AOSP/system/extras/simpleperf/script

常用脚本:

  • app_profiler.py:用于录制,在主机上执行 simpleperf。
  • run_simpleperf_on_device.py:用于录制,在手机上执行 simpleperf。
  • gecko_profile_generator.py:用于转换 perf.data 文件用于可视化工具解析。

操作步骤

  1. record 录制;
  • 使用 run_simpleperf_on_device.py:
./run_simpleperf_on_device.py record --app <包名> -g --duration <时间> -o /data/local/tmp/perf.data
  • 使用 app_profiler.py:
./app_profiler.py --pid <应用PID> -r "-e cpu-clock -g --duration <时间> -o /data/local/tmp/perf.data"
# native 进程
./app_profiler.py --np <进程名> -r "-e cpu-clock -g --duration <时间> -o /data/local/tmp/perf.data"
  1. 拉出生成的分析数据文件;
  2. report 转换 perf.data 成 UI 工具可以解析的格式;
./gecko_profile_generator.py -i ./perf.data | gzip > perf.json.gz

使用 UI 工具查看分析数据文件

Firefox⁩ 性能分析网页应用程序

例子: 图片.png

三、常见问题

  1. “Can't create output file in directory .: Read-only file system”
$ simpleperf record  -p 9643 -e cpu-clock -g --duration 5                                          
simpleperf E cmd_record.cpp:532] Can't create output file in directory .: Read-only file system

使用 “-o” 指令重定向目标文件位置。

$ simpleperf record  -p 9643 -e cpu-clock -g --duration 5 -o sdcard/perf.data                        
simpleperf I cmd_record.cpp:798] Recorded for 5.01924 seconds. Start post processing.
simpleperf I cmd_record.cpp:891] Samples recorded: 0. Samples lost: 0.
  1. 运行 simpleperf 的 Python 脚本需要 Python3.9及以上版本,如果不想升级可以使用3.8并修改 simpleperf_utils.py。 图片.png

参考文档:

Android Simpleperf 官方文档

AOSP Simpleperf 源码文档