Perf 使用说明
:::info 文档信息
发布版本:1.0 · 页数:8 · 语言:中文
原始文档:Rockchip_Quick_Start_Linux_Perf_CN.pdf
:::
章节大纲
- Perf 使用说明(P1)
- 1 介绍(P1)
- 2 功能(P2)
- 3 在 Android 平台使用(P2)
- 3.1 准备工作(P2)
- 3.2 获取当前平台支持的事件(P4)
- 3.3 获取系统热点进程(P4)
- 3.4 获取进程的统计信息(P5)
- 3.5 收集进程的 profile 数据(P5)
- 3.6 分析 profile 数据(P5)
- 3.7 FlameGraph(P6)
- 4 在 Linux 平台使用(P6)
- 5 Simpleperf 使用(P8)
在线预览
若预览无法显示,请直接下载 PDF 后用本地阅读器打开。
| 芯片名称 | 内核版本 |
|---|---|
| 全系列 | 4.4 |
| 日期 | 版本 | 作者 | 修改说明 |
|---|---|---|---|
| 2017-12-25 | V1.0 | 陈谋春 |
1 介绍2 功能3 在 Android 平台使用3.1 准备工作3.2 获取当前平台支持的事件3.3 获取系统热点进程3.4 获取进程的统计信息3.5 收集进程的 profile 数据3.6 分析 profile 数据3.7 FlameGraph 4 在 Linux 平台使用5 Simpleperf 使用
1 介绍
Perf 是从 Linux 2.6 开始引入的一个 profiling 工具,通过访问包括 pmu 在内的软硬件性能计数器来分析性能,支持多架构,是目前 Kernel 的主要性能检测手段,和 Kernel 代码一起发布,所以兼容性良好。
2 功能
性能瓶颈如果要分类的话,大致可以分为几个大类:cpu/gpu/mem/storage,其中 gpu 用 Perf没法探测(这个目前比较好用的工具就只有 DS5),storage 只能用 tracepoint 来统计。总的说来,Perf 还是侧重于分析 cpu 的性能,其他功能都不是很好用。
$ perf
usage: perf [--version] [--help] COMMAND [ARGS]
The most commonly used perf commands are: annotate Read perf.data (created by perf record) and display annotated code archive Create archive with object files with build-ids found in perf.data file bench General framework for benchmark suites buildid-cache Manage <tt>build-id</tt> cache. buildid-list List the buildids in a perf.data file diff Read two perf.data files and display the differential profile inject Filter to augment the events stream with additional information kmem Tool to trace/measure kernel memory(slab) properties kvm Tool to trace/measure kvm guest os list List all symbolic event types lock Analyze lock events probe Define new dynamic tracepoints record Run a command and record its profile into perf.data report Read perf.data (created by perf record) and display the profile sched Tool to trace/measure scheduler properties (latencies) script Read perf.data (created by perf record) and display trace output stat Run a command and gather performance counter statistics test Runs sanity tests. timechart Tool to visualize total system behavior during a workload top System profiling tool.
See 'perf help COMMAND' for more information on a specific command.
其中比较常用的功能有几个:
record:收集 profile 数据report:根据 profile 数据生成统计报告stat:打印性能计数统计值top:cpu 占有率实时统计
3 在 Android 平台使用
3.1 准备工作
- 首先按 Google 或芯片厂商的指导,构建一个完整的 Android 和 Kernel 的编译环境(如果不关心Kernel 可以忽略), 这样分析的时候符号表才能匹配上。2. 编译 Perf
~$ . build/envsetup.sh ~$ lunch ~$ mmm external/linux-tools-perf ~$ adb root ~$ adb remount ~$ adb push perf /system/bin/ ~$ adb shell sync
- 准备符号文件符号文件可以简单分为三类:a. 平台 native 代码,这部分代码在编译的过程中会自动生成符号表,不需要我们干预b. 平台 java 代码,对于 art 虚拟机来说(老版本的 dalvik 就不说了)最终的编译结果是 oat 文件,这也是正规的 elf 文件,但是默认是不带 debug 信息。而新版本的 Android 也提供了自动生成 java 符号表的工具:
bash art/tools/symbolize.sh
c. 第三方 apk,如果是来自开源社区,则可以通过修改 makefile 和套用 Android 提供的 java 符号表工具来生成符号表文件,然后拷贝到 Android 的符号表目录,==注意路径必须要和设备上的完全一致==,可以通过 showmap 来获取设备上的路径。
~$ adb shell showmap apk_pid 38540 36296 36296 0 0 36216 80 0 3 /data/app/com.android.webview-2/lib/arm/libwebviewchromium.so ~$ cp libwebviewchromium.so $ANDROID_PRODUCT_OUT/symbols/data/app/com.android.webview- 2/lib/arm/libwebviewchromium.so
如果是商业的 apk,基本上已经做过混淆和 strip,除非开发商能配合,不然就没招。
- 稍微新一点的 Android 都开起了 Kernel 的指针保护,这也会影响 Perf 的 record,所以需要临时关闭保护:
~$ adb shell echo 0 > /proc/sys/kernel/kptr_restrict
- 为了方便分析,一般会把 record 的数据 pull 到 host 端,在 host 端做分析,所以需要在设备端也安装一下 Perf 工具,ubuntu 下安装命令如下:
~$ sudo apt-get install linux-tools-common
- 目前大部分的 Android 平台默认 Perf 功能都是打开的,所以一般不需要重新配置 Kernel,如果碰到 Perf 被关闭的情况,可以打开下面几个配置
CONFIG_PERF_EVENTS=y CONFIG_HW_PERF_EVENTS=y
3.2 获取当前平台支持的事件
rk3399:/data/local # ./perf list List of pre-defined events (to be used in -e): cpu-cycles OR cycles [Hardware event] instructions [Hardware event] cache-references [Hardware event] cache-misses [Hardware event] branch-instructions OR branches [Hardware event] branch-misses [Hardware event] bus-cycles [Hardware event]
cpu-clock [Software event] task-clock [Software event] page-faults OR faults [Software event] context-switches OR cs [Software event] cpu-migrations OR migrations [Software event] minor-faults [Software event] major-faults [Software event] alignment-faults [Software event] emulation-faults [Software event] dummy [Software event]
L1-dcache-loads [Hardware cache event] L1-dcache-load-misses [Hardware cache event] L1-dcache-stores [Hardware cache event] L1-dcache-store-misses [Hardware cache event] L1-dcache-prefetch-misses [Hardware cache event] L1-icache-loads [Hardware cache event] L1-icache-load-misses [Hardware cache event] dTLB-load-misses [Hardware cache event] dTLB-store-misses [Hardware cache event] iTLB-load-misses [Hardware cache event] branch-loads [Hardware cache event] branch-load-misses [Hardware cache event]
实际上 Android 移植的 Perf 还不完整,tracepoint 的事件还不支持,例如:block 事件,所以如果想要抓去一些内核子系统的性能信息就无法满足。Android 7.0 开始已经去掉了 Perf 工具,替代它的是Simpleperf 1 工具,对 tracepoint 的支持比原来的好很多。
3.3 获取系统热点进程
Perf 中的 top 工具可以列出当前 cpu 的热点,还可以附加 Kernel 的符号表让信息可方便分析。命令如下:
$ adb shell mkdir -p /data/local/symbols
$ adb push vmlinux /data/local/symbols/vmlinux
$ adb shell
# perf top --vmlinux=/path/to/vmlinux -d 2
结果输出如下:perf top 还可以只抓取指定进程的 pid,这一般是用在要优化某个程序是非常有用,命令如下:
perf top --vmlinux=/path/to/vmlinux -d 2 -p pid_of_prog
perf top 还和系统的 top 一样可以指定刷新间隔 2 , 以上命令中的-d 选项就是这个功能,单位是秒。
3.4 获取进程的统计信息
perf stat 用于获取进程某个时间段内的 pmu 统计信息,命令如下:
# ./perf stat -p 1415
ctrl+c 退出,或发信号让 Perf 进程退出都可以看到统计结果,例如:
一些明显的异常值会被标注为红色,例如上图是浏览器跑 fishtank 时候抓的统计信息,可以看到分支预测的失败率非常高,结合 Perf 的热点分析工具可以进一步缩小范围找到分支预测失败的原因。
3.5 收集进程的 profile 数据
perf record 用于记录详细的 profile 数据,可以指定记录某个进程,还可以记录调用栈,命令如下:
# perf record -g -p pid -o /data/local/perf.data
也可以指定只抓取某个事件,事件列表可以通过上面的 perf list 得到,例如:
# ./perf record -e cache-misses -p 1415
3.6 分析 profile 数据
perf report 用户分析抓到的 profile 数据,一般会先把数据发到 pc 上再分析,命令如下:
adb pull /data/local/perf.data
perf report --objdump=aarch64-linux-android-objdump --vmlinux=/path/to/vmlinux - -symfs ANDROID_PRODUCT_OUT/symbols -i perf.data
结果如图:
上图有‘+’的地方可以用‘enter’键来遍历其调用关系。
3.7 FlameGraph
还可以通过一些脚本来方便分析调用关系,Flame Graph 就是一个比较好用的可视化分析工具。
下载:
git clone https://github.com/brendangregg/FlameGraph.git
生成图形:
perf script --vmlinux=<kernel_folder>/vmlinux --symfs $ANDROID_PRODUCT_OUT/symbols -i perf.data | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.html
4 在 Linux 平台使用
arm 版本的 linux 发行版很多都没有提供 Perf 的包,所以需要自己手动编译一个 Perf,由于 Perf 依赖的 elfutils/binutils/zlib,所以实际上需要交叉编译四个东西。
首先编译 zlib,源码地址CC=aarch64-linux-gnu-gcc ./configure -- prefix=/home/cmc/workspace/linaro/toolchain/armlinux/aarch64/gcc-linaro-6.3.1- 2017.02-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/libc/usr
make && make install
==Note: prefix 要指向你的交叉编译工具的库目录==
编译 elfutils,我直接用的最新的版本的:
git clone git://sourceware.org/git/elfutils.git
配置:
cd /path/to/elfutils
mkdir build ./configure --enable-maintainer-mode --host=aarch64-linux-gnu -- prefix=/home/cmc/workspace/linaro/elfutils/build
修改 Makefile: 删除 elfutils 根目录下 Makefile 里面的 libcpu
修改 backends/Makefile: 删除 backends/Makefile 中的 libebl_i386 和 libebl_x86_64 有关的所有东西
编译:
make && make install
编译 binutils,这个要考虑和 gcc 版本的兼容,我用的 2.28.1 的版本,源代码地址
cd /path/to/binutils
mkdir build ../configure --target=aarch64-linux-gnu --host=aarch64-linux-gnu -- prefix=/home/cmc/workspace/linaro/binutils-2.28.1/build
make && make install
编译 Perf,Perf 是 Kernel 一起发布的,所以直接下载一个 Kernel 就有了,但是交叉编译的话,需要改一些东西:
修改 Makefile.perf,在前面加入:
EXTRA_CFLAGS=-I/path/to/elfutils/build/inclue -L/path/to/elfutils/build/lib - I/path/to/binutils/build/include -L/path/to/binutils/build/lib WERROR=0 NO_LIBPERL=1 NO_LIBPYTHON=1
编译
cd /path/to/kernel/tools/perf
make -f Makefile.perf perf ARCH=arm64
CROSS_COMPILE=/home/cmc/workspace/linaro/toolchain/armlinux/aarch64/gcc-linaro- 6.3.1-2017.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- -j8理论上在 arm 的 linux 发行版上直接编译 Perf 应该也是可以的,但是我没有试过。用法的话和Android 是一样的,这里就不叙说了。
5 Simpleperf 使用
Android 7.0 开始提供了一个更完整的 Perf 版本 Simpleperf:
source build/envsetup.sh
lunch mmma system/extras/simpleperf
Simpleperf 相对之前 google 移植的 Perf 有以下改进
支持剖析 apk 中兼容的共享库,从 .gnu_debugdata 段读取符号表和调试信息提供更方便分析的脚本纯静态,所以和 Android 版本无关,只要指令集兼容都能跑
ndk r13 开始就提供了 Simpleperf 工具,所以也可以直接下载编译好的工具:
git clone https://aosp.tuna.tsinghua.edu.cn/platform/prebuilts/simpleperf
用法上和 Perf 是类似的,命令基本通用,可以直接参考上面 Perf 的命令。
Simpleperf 更多信息, 特别是调试 java 程序的方法,请参考官方手册
-
后面也会简单介绍一些Simpleperf↩
-
这个是指top统计信息的刷新间隔而不是采样间隔↩