simpleperf源码:https://android.googlesource.com/platform/system/extras/+/master/simpleperf
Flame Graphs官方博客(火焰图的源资料皆出自该博客):https://www.brendangregg.com/flamegraphs.html
火焰图处理脚本和示例:git clone https://github.com/brendangregg/FlameGraph.git
一、火焰图简介
1. 火焰图的作用:可以分析函数CPU运行耗时、函数阻塞、函数频繁分配内存。火焰图把大量信息压缩到一个大小相对固定的图片当中,方便对比查看。
2. 可以采样单线程、多线程、单个app、多进程,或整个系统。
二、火焰图种类
常见的火焰图类型有 On-CPU,Off-CPU,还有 Memory,Hot/Cold,Differential 等等,它们有各自适合处理的场景。
1. on-cpu火焰图
横轴含义是cpu占用时间,纵轴含义是调用栈,以固定频率采样cpu调用栈,主要用于解决cpu占用高的问题。
2. off-cpu火焰图
横轴含义是cpu阻塞时间,纵轴含义是调用栈,以固定频率采样阻塞事件调用栈,主要用于解决IO/网络/休眠锁竞争导致的性能下降问题。
3. 内存火焰图
横轴含义是内存申请释放函数的调用次数,纵轴含义是调用栈,通过跟踪malloc/free、brk、mmap、page-faul实现,主要用于解决内存泄露、内存分配释放频繁问题。
4. Hot/Cold火焰图
横轴含义是on-cpu和off-cpu的综合展示,纵轴含义是调用栈,采用on-cpu和off-cpu综合的方式,主要用于需要结合CPU占用和阻塞一起分析的场景。
三、火焰图生成
1. 环境准备
需要有simpleperf命令行工具,simpleperf源码(需要使用里面的脚本)、FlameGraph源码(要用到里面的脚本,需要下载下来)。
git clone https://github.com/brendangregg/FlameGraph.git
2. 生成火焰图
比如,要获取com.sam.appstore冷启动场景对CPU的占用详细信息,可通过如下方法生成对应的火焰图
//车机上执行 # simpleperf record --app com.sam.appstore -g --duration 1 -o /sdcard/simpleperf_appstore_1s.data //Android工程simpleperf源码路径中执行: system/extras/simpleperf/scripts$ python report_sample.py simpleperf_appstore_1s.data > simpleperf_appstore_1s_report.data //FlameGraph源码路径中执行: ~/tmp/FlameGraph$ ./stackcollapse-perf.pl simpleperf_appstore_1s_report.data > simpleperf_appstore_1s_report_fold.data ~/tmp/FlameGraph$./flamegraph.pl simpleperf_appstore_1s_report_fold.data > simpleperf_appstore_1s_report_fold.svg使用Google浏览器打开 simpleperf_appstore_1s_report_fold.svg 就是想要得到的On-Cpu火焰图,放在本文档附件上了,打开如下图1。 图1:
鼠标放在对应的条目上会显示采样命中次数和占比。
3. 生成差分火焰图
有时需要改动前后,或两个版本间的对比,这时差分火焰图比较有用,生成方法:
//FlameGraph源码路径中执行: ~/tmp/FlameGraph$ ./difffolded.pl simpleperf_appstore_1s_report_fold.data simpleperf_appstore_1s_2_report_fold.data > simpleperf_appstore_1s_diff.data ~/tmp/FlameGraph$ ./flamegraph.pl simpleperf_appstore_1s_diff.data > simpleperf_appstore_1s_diff.svg
为了方便,可以将命令组合写在一起:
//生成火焰图 ~/tmp/FlameGraph$ ./stackcollapse-perf.pl simpleperf_appstore_1s_report.data | ./flamegraph.pl > simpleperf_appstore_1s_report_fold.svg //生成差分火焰图 ~/tmp/FlameGraph$ ./difffolded.pl simpleperf_appstore_1s_report_fold.data simpleperf_appstore_1s_2_report_fold.data | ./flamegraph.pl > simpleperf_appstore_1s_diff.svg使用Google浏览器打开 simpleperf_appstore_1s_diff.svg 就是想要得到的差分火焰图,放在本文档附件上了,打开如下图2。 图2:
四、脚本选项
1. stackcollapse-perf.pl
~/tmp/FlameGraph$ ./stackcollapse-perf.pl --help USAGE: ./stackcollapse-perf.pl [options] infile > outfile --pid # 包含进程名称的 PID [1] --tid # 包含进程名称的 TID 和 PID [1] --inline # 使用 addr2line 取消内联 --all # 所有注释 (--kernel --jit) --kernel # 使用 _[k] 注释内核函数 --jit # 使用 _[j] 注释 jit 函数 --context # 将源上下文添加到 --inline --srcline # 解析“perf script -F+srcline”的输出并添加源上下文 --addrs # 包含无法找到符号的原始地址 --event-filter=EVENT # 事件名称过滤器
测试:
使用 --inline 和不使用这个的同一份perf数据进行对比 ==> 生成的全是蓝色的了(淡白色)。
使用 --kernel --jit ==> 对simpleperf都毫无用处。
2. difffolded.pl
~/tmp/FlameGraph$ ./difffolded.pl --help USAGE: ./difffolded.pl [-hns] combined1 combined2 | flamegraph.pl > diff2.svg -h # 帮助信息 -n # 标准化样本计数 -s # 删除十六进制数字(地址)
3. flamegraph.pl
~/tmp/FlameGraph$ ./flamegraph.pl --help USAGE: ./flamegraph.pl [options] infile > outfile.svg --title TEXT # 更改标题文本 --subtitle TEXT # 第二级标题(可选) --width NUM # 图像宽度(默认 1200) --height NUM # 每帧高度(默认 16) --minwidth NUM #省略较小的函数。以像素为单位或使用“%”表示时间百分比(默认 0.1 像素) --fonttype FONT # 字体类型(默认“Verdana”) --fontsize NUM # 字体大小(默认 12) --countname TEXT # 计数类型标签(默认“samples”) --nametype TEXT # 名称类型标签(默认“Function:”) --colors PALETTE # 设置调色板。选项有:hot(默认)、mem、io、wakeup、chain、java、js、perl、red、green、blue、aqua、yellow、purple、orange --bgcolors COLOR # 设置背景颜色。渐变选项有 yellow(默认)、blue、green、grey;纯色使用“#rrggbb” --hash # 颜色由函数名称 hash 键控 --random # 颜色随机生成 --cp # 使用一致调色板 (palette.map) --reverse # 生成堆栈反转火焰图 --inverted # 冰柱图 --flamechart # 生成火焰图(按时间排序,不合并堆栈) --negate # 切换差异色调(蓝色<->红色) --notes TEXT # 在 SVG 中添加注释(用于调试) --help # 打印此消息 例如, ./flamegraph.pl --title="Flame Graph: malloc()" trace.txt > graph.svg
测试:
--hash ==> 生成的火焰图颜色有区别,各条目颜色更相近,不易区分
--reverse ==> 加reverse更难分析了,并不只是颜色变化不同
--inverted ==>火焰图向下烧了,没有默认的好,会导致鼠标放在某个条目上后由于图太高导致在最底部显示的信息看不到。
--flamechart ==>看不出来好坏,可能各有作用吧
--negate ==> 图的形状完全一样,只是颜色上红蓝互换了。
--title ==> 的确可以加标题,上面的 "Flame Graph: malloc()" 可以显示出来。
五、火焰图分析
使用Google浏览器打开生成的火焰图.svg文件。
1. svg文件简介
每一列代表一个调用栈,每一个格子代表一个函数。格子的宽度代表其在采样中出现频率,所以一个格子的宽度越大,说明它是瓶颈的可能性就越大。
纵轴展示了栈的深度,按照调用关系从下到上排列。
横轴的含义:火焰图将采集的多个调用栈信息,通过按字母横向排序的方式聚合在一起。需要注意的是它并不代表时间。
火焰图格子的颜色是随机的暖色调,只为方便区分各个调用信息。
2. svg文件支持的操作
(1) 点击某条目进行放大,点击"Reset Zoom"恢复。
(2) 鼠标放在某条目上,会显示采样次数和占比。比如放在 art_jni_trampoline, 左下角显示 "Functon: art_jni_trampoline(1,034,730,160 samples, 23.99%)" 表示此函数采样命中次数是总次数的23.99%。
(3) Ctrl+F进行查找,命中的条目会以紫色高亮显示出来,点击"Reset Search"恢复。
六、火焰图局限
1. 调用栈不完整。当调用栈过深时,可能只返回前面一部分。
2. 函数名缺失。有些函数没有名字,使用内存地址来表示。
标签:1s,--,火焰,appstore,simpleperf,初探,pl From: https://www.cnblogs.com/hellokitty2/p/18294801