1. 火焰图的概念
以下是比较官方的解释:
一种软件执行情况的形象化的反映,用于做性能profile和debug。
在Flame Graph在呈现出整个最终结果之前,其中主要的工作并不是图形的展现,而是前面profile数据的采集。
这里数据的采集首先按照profile的类型分为以下几类:
- (1)CPU的profile分析,那需要进行的stack trace的采集,可以借助于Linux的perf命令
- (2)Off-CPU的profile,那些没有消耗CPU的线程的profile,可以理解为被block住的线程。
以上不同类型的profile需要依赖不同的采集工具,对于CPU的profile,它要做的其实就是进程stack trace的收集。这个收集可以按照采集总时间,采集频率来进行。
2. CPU的profile分析
我们要分析的是某个任务在cpu被执行的过程中,具体的调用栈长啥样。所以我们关注的是这个任务在运行态时,执行它的cpu的栈长啥样。
因此,明确当此任务不在cpu上的时候(处于就绪态或者阻塞态),该cpu采样的结果不统计。
执行:
perf record -F 99 -a -g -p $pid -- sleep 1
就表示在所有cpu上,在1s的时间窗口内,每1/99s的时间间隔采样。如下图,示例了一个cpu上采样的过程。
<div align=center>
</div>
然后收集当前指令地址(程序计数器)或整个堆栈信息——得到99个快照,我们把这99个快照聚合,Off-CPU阶段,perf采集不到cpu上这个任务的任何信息,所以下图参与聚合的快照,可能只有80张。这样我们就得到了该cpu上一个包含统计信息的数据。
<div align=center>
</div>
实际上的多CPU得到的统计结果是很乱的,生成的stack trace全部展现出来会相当的庞大。虽然perf命令可以帮助对此进行折叠,汇总,但是仍然不便于我们分析。所以火焰图就是我们最后一步使用的聚合工具。展现效果如下图中所示。
<div align=center>
</div>
上述图中,y轴高度表示的stack trace的调用深度,从上往下为从child–>parent的关系,x轴宽度表示调用的频率,所以我们在观察flame Graph的时候,要观察最顶部的那些宽度比较宽的stack信息。Flame Graph通过图形的方式能够帮助开发者迅速定位出明显消耗资源的调用
3. 一个案例:On-cpu火焰图分析fm_item性能
略
4. cpu利用率太高的一些优化措施
- (1)减少多余的操作,例如案例里的map search,json obj里的findMember代替hasMember,obj[member_name]的方式。
- (2)减少数据的深拷贝。
- (3)局部性原理,对数组按行进行访问时,具有更好的空间局部性,Cache命中率更高。
5. On-cpu火焰图分析的简要步骤:
官网资料:http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html
(1)准备工作:服务器上下载好包FlameGraph.tar.gz并解压
wget http://minio.eos.grid.sina.com.cn:9100/software/FlameGraph.tar.gz(2)先启动进程,再启动perf记录,sleep后的参数是指perf采集的时间 99表示的采样频率,pid就是我们要测量的进程id
perf record -F 99 -a -g -p $pid -- sleep 60-
(3)perf 进程结束后,数据记录在perf.data中,如下图:
<div align=center>
image.png
</div>
(4)接下来执行生成out.perf-folded中间文件
perf script | ./FlameGraph/stackcollapse-perf.pl > out.perf-folded(5)接着继续执行,把out.perf-folded转换成perf-kernel.svg文件:
./FlameGraph/flamegraph.pl out.perf-folded > perf-kernel.svg(6)启动一个web server 比如运行python -m SimpleHTTPServer 8080
出现如下页面,点击红色箭头指向的perf-kernel.svg即可显示火焰图:
<div align=center>
</div>
最后就得到长这个样子的火焰图了,接下来的目标就是看看那些调用栈大平顶对应的函数,找到优化的方法。
<div align=center>
</div>