火焰图性能分析
前言
应用程序性能一直是软件开发过程中一个很重要的话题,性能的好坏不仅会直接影响到所消耗的资源和投入的金钱, 而且会直接影响到用户的使用体验,从而间接影响一款产品的生命周期。
在软件开发过程中,一般会使用多种手段来量化性能、追踪性能问题等。比如使用ab
及wrk
等工具来压测网络应用,使用Zipkin
或Opentracing
等跟踪性能问题,使用日志来定位性能问题,使用gdb
等工具调试性能问题。
而火焰图是一个可以让你直观了解性能问题的方式,最终一般会生成一张SVG格式的图片,你可以会方便地进行缩放以及进一步查看局部区域,如下所示。
关于火焰图
生成火焰图,需要经历采集、转化、渲染等多个步骤,不同步骤需要用到不同的工具。
首先,我们需要进行性能数据采集。只有收集到足够的数据后,才能进行相应的分析。
性能采集工具不同操作系统各有不同,在Linux操作系统中常用的有Perf
和Systemtap
这两种工具。
在采集到数据后,需要对数据进行处理,以获得相应格式化的数据。 使用FlameGraph可以对这两种工具采集来的数据进行处理,生成可以渲染的数据。 同时,FlameGraph也可以将处理完成的数据生成SVG图片,以供仔细分析。
Openresty应用作者在使用火焰图过程中,总结出了一套相应的性能采集工具集Openresty systemtap toolkit,来采集各种不同类型的性能数据。
采集性能数据的类型有几种,主要是下面几种:
- On CPU 当CPU占用率比较高时使用
- Off CPU 当CPU占用率并不高,性能瓶颈位于IO或者锁等地方时使用
- Memory 当可能出现内存泄露时使用
- Hot/Cold 试验性质,联合CPU的两种类型,相当于
On CPU
+Off CPU
使用Perf
采集数据
perf
是Linux系统下的一个性能采集工具,只能用于Linux系统。更详细的perf
使用方法,请参考 perf Examples。
安装
perf
工具Ubuntu 16.04
sudo apt install -y linux-tools-`uname -r`
CentOS 7
sudo yum install perf
运行perf --help
命令,如果出现类似下面的提示
WARNING: perf not found for kernel 4.4.0-81
You may need to install the following packages for this specific kernel:
linux-tools-4.4.0-81-generic
linux-cloud-tools-4.4.0-81-generic
You may also want to install one of the following packages to keep up to date:
linux-tools-generic
linux-cloud-tools-generic
按照相应提示,进行安装即可,如:sudo apt install -y linux-tools-4.4.0-81-generic
安装完成后,就可以对相应的程序进行性能采集了。在进行采集时候,为了更显著地看到效果(特别是在测试时候,程序调用量很小,很难看出效果),可以对程序进行压力测试来配合性能采集。
获取目标程序的
pid
。通过ps
即可查看到(将XXX替换为相应程序名称):sudo ps aux | grep XXX
通过
perf
工具进行采集(将下面命令中的PID
替换成真实的PID,各参数的含义请参考文档 ):# 采集 On-CPU 性能数据 perf record -F 99 -p PID -g -- sleep 60 # 采集 Memory 分配释放 perf record -e kmem:* -p PID
通过上面的
perf record
命令,会在当前目录下生成一个名为perf.data
的文件。处理采集来的数据(在
perf.data
所在目录下执行):perf script > out.perf #perf script -i perf.data > out.perf
使用Systemtap
采集数据
Systemtap 是一种在运行时收集系统信息的基础架构,可以动态监控和跟踪运行中的 Linux 内核的操作。
安装
systemtap
工具链CentOS 7
rpm -ivh kernel-debuginfo-$(uname -r).rpm rpm -ivh kernel-debuginfo-common-$(uname -r).rpm rpm -ivh kernel-devel-$(uname -r).rpm yum install systemtap
Debian 9
apt-get install systemtap linux-image-`uname -r`-dbg linux-headers-`uname -r`
Ubuntu 16.04
在Ubuntu上安装systemtap
有些麻烦,可以参考篇文章Ubuntu Systemtap进行安装
在安装完成后,为了方便采集,可以安装openresty-systemtap-toolkit工具包,以下示例就是采用此工具包进行操作。
- 获取目标程序
pid
(与上面相同) 使用工具集进行采集
cd openresty-systemtap-toolkit # 采集 On-CPU 性能数据 ./sample-bt -p PID -t 5 -u > sample.bt # 采集 Off-CPU 性能数据 ./sample-bt-off-cpu -u -p PID -t 5 -df > sample.bt
生成火焰图
需要先把采集来的数据转化为对应的格式,然后再将其生成火焰图。 转化格式与生成火焰图的脚本都是由FlameGraph这个项目提供的。
转化
perf
采集来的数据# On-CPU 数据 ./stackcollapse-perf.pl out.perf > out.folded # Off-CPU 数据 ./stackcollapse.pl out.perf > out.folded
转化
systemtap
采集来的数据./stackcollapse-stap.pl sample.bt > out.foled
使用flamegraph.pl
可以将转化后的数据生成SVG图片,如下:
./flamegraph.pl out.folded > result.svg
对于两次采集目标程序而得到的不同数据,还可以使用difffolded.pl
进行对比生成差异火焰图
# 注意,前后次序不同会生成不同的差异图。其实也可以利用这个特性来进行改进分析。
./difffolded.pl out1.folded out2.folded | ./flamegraph.pl > diff.svg
在差异火焰图中,红色代表增长,蓝色代表减少
PS: 本文只是简单梳理了下火焰图生成流程,对于详细的使用步骤及参数说明并没有过多的深入。 如果有需要,可以通过参考资料进一步地了解和使用。