火焰图性能分析

· Read in about 2 min · (270 Words)
dev tool

前言

应用程序性能一直是软件开发过程中一个很重要的话题,性能的好坏不仅会直接影响到所消耗的资源和投入的金钱, 而且会直接影响到用户的使用体验,从而间接影响一款产品的生命周期。

在软件开发过程中,一般会使用多种手段来量化性能、追踪性能问题等。比如使用abwrk等工具来压测网络应用,使用ZipkinOpentracing等跟踪性能问题,使用日志来定位性能问题,使用gdb等工具调试性能问题。

而火焰图是一个可以让你直观了解性能问题的方式,最终一般会生成一张SVG格式的图片,你可以会方便地进行缩放以及进一步查看局部区域,如下所示。 Riki Graph

关于火焰图

生成火焰图,需要经历采集、转化、渲染等多个步骤,不同步骤需要用到不同的工具。

首先,我们需要进行性能数据采集。只有收集到足够的数据后,才能进行相应的分析。 性能采集工具不同操作系统各有不同,在Linux操作系统中常用的有PerfSystemtap这两种工具。

在采集到数据后,需要对数据进行处理,以获得相应格式化的数据。 使用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

安装完成后,就可以对相应的程序进行性能采集了。在进行采集时候,为了更显著地看到效果(特别是在测试时候,程序调用量很小,很难看出效果),可以对程序进行压力测试来配合性能采集。

  1. 获取目标程序的pid。通过ps即可查看到(将XXX替换为相应程序名称):

    sudo ps aux | grep XXX
    
  2. 通过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的文件。

  3. 处理采集来的数据(在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工具包,以下示例就是采用此工具包进行操作。

  1. 获取目标程序pid(与上面相同)
  2. 使用工具集进行采集

    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: 本文只是简单梳理了下火焰图生成流程,对于详细的使用步骤及参数说明并没有过多的深入。 如果有需要,可以通过参考资料进一步地了解和使用。

参考资料

Comments