宋宝华:火焰图:全局视野的Linux性能剖析

原创 2017年11月14日 10:43:49

简介

火焰图(Flame Graph)是由Linux性能优化大师Brendan Gregg发明的,本文用最简单的实例讲解什么是火焰图,怎么画出来火焰图,火焰图的优点是什么。

什么是火焰图

火焰图(Flame Graph)是由Linux性能优化大师Brendan Gregg发明的,和所有其他的trace和profiling方法不同的是,Flame Graph以一个全局的视野来看待时间分布,它从底部往顶部,列出所有可能的调用栈。其他的呈现方法,一般只能列出单一的调用栈或者非层次化的时间分布。

我最快乐的童年时代,每逢冬天,尤其是春节的时候,和一家人围坐在火堆旁边烤火。这已经成为最美好的回忆,其实人生追求的快乐非常简单。火焰图的火焰首先来自于根,然后以火苗的形式往上面窜。可以把从靠近地面的根到顶上的每个火苗,想想成一个调用栈。由于火苗有很多根,这正好也和现实生活中程序的执行逻辑相似。


以典型的分析CPU时间花费到哪个函数的on-cpu火焰图为例来展开。

CPU火焰图中的每一个方框是一个函数,方框的长度,代表了它的执行时间,所以越宽的函数,执行越久。火焰图的楼层每高一层,就是更深一级的函数被调用,最顶层的函数,是叶子函数。



火焰图的生成过程是:

  1. 先trace系统,获取系统的profiling数据 

  2. 用脚本来绘制


系统的profiling数据获取,可以选择最流行的perf record,而后把采集的数据进行加工处理,绘制为火焰图。其中第二步的绘制火焰图的脚本程序,通过如下方式获取:

git clone https://github.com/brendangregg/FlameGraph

火焰图案例

废话不多说,直接从最简单的例子开始说起。talk is cheap, show you the cde,代码如下:

c()

{

    for(int i=0;i<1000;i++);

}

b()

{

    for(int i=0;i<1000;i++);

    c();

}

a()

{

    for(int i=0;i<1000;i++);

    b();

}

则这三个函数,在火焰图中呈现的样子为:


a()的2/3的时间花在b()上面,而b()的1/3的时间花在c()上面。很多个这样的a->b->c的火苗堆在一起,就构成了火焰图。


进一步理解火焰图的最好方法仍然是通过一个实际的案例,下面的程序创建2个线程,两个线程的handler都是thread_fun(),之后thread_fun()调用fun_a()、fun_b()、fun_c(),而fun_a()又会调用fun_d():

/*

 * One example to demo flamegraph

 *

 * Copyright (c) Barry Song

 *

 * Licensed under GPLv2

 */


#include <pthread.h>


func_d()

{

    int i;

    for(i=0;i<50000;i++);

}


func_a()

{

    int i;

    for(i=0;i<100000;i++);

    func_d();

}


func_b()

{

    int i;

    for(i=0;i<200000;i++);

}


func_c()

{

    int i;

    for(i=0;i<300000;i++);

}


void* thread_fun(void* param)

{

    while(1) {

        int i;

        for(i=0;i<100000;i++);

        

        func_a();

        func_b();

        func_c();

    }

}


int main(void)

{

    pthread_t tid1,tid2;

    int ret;

    

    ret=pthread_create(&tid1,NULL,thread_fun,NULL);

    if(ret==-1){

        ...

    }

    

    ret=pthread_create(&tid2,NULL,thread_fun,NULL);

    ...

    

    if(pthread_join(tid1,NULL)!=0){

        ...

    }

    

    if(pthread_join(tid2,NULL)!=0){

        ...

    }

    

    return 0;

}

先看看不用火焰图的缺点在哪里。

如果不用火焰图,我们也可以用类似perf top这样的工具分析出来CPU时间主要花费在哪里了:

$gcc exam.c -pthread

$./a.out&

$sudo perf top

perf top的显示结果如下:


perf top提示出来了fun_a()、fun_b()、fun_c(), fun_d(),thread_func()这些函数内部的代码是CPU消耗大户,但是它缺乏一个全局的视野,我们无法看出全局的调用栈,也弄不清楚这些函数之间的关系。火焰图则不然,我们用下面的命令可以生成火焰图(以root权限运行):

perf record -F 99 -a -g -- sleep 60

perf script | ./stackcollapse-perf.pl > out.perf-folded

./flamegraph.pl out.perf-folded > perf-kernel.svg

上述程序捕获系统的行为60秒钟,最后调用flamegraph.pl生成一个火焰图perf-kernel.svg,用看图片的工具就可以打开这个svg。

上述火焰图显示出了a.out中,thread_func()、func_a()、func_b()、fun_c()和func_d()的时间分布。

从上述火焰图可以看出,虽然thread_func()被两个线程调用,但是由于thread_func()之前的调用栈是一样的,所以2个线程的thread_func()调用是合并为同一个方框的。

更多阅读

除了on-cpu的火焰图以外,off-cpu的火焰图,对于分析系统堵在IO、SWAP、取得锁方面的帮助很大,有利于分析系统在运行的时候究竟在等待什么,系统资源之间的彼此伊伴。

比如,下面的火焰图显示,nginx的吞吐能力上不来的很多程度原因在于sem_wait()等待信号量。



上图摘自Yichun Zhang (agentzh)的《Introduction to off-CPU Time Flame Graphs》。


关于火焰图的更多细节和更多种火焰图各自的功能,可以访问: 

http://www.brendangregg.com/flamegraphs.html


本文首发于Linuxer微信公众号(ID: LinuxDev),转发回blog。扫描二维码关注Linuxer~


宋宝华:火焰图:全局视野的Linux性能剖析

作者简介 宋宝华,他有10几年的Linux开发经验。他长期在大型企业担任一线工程师和系统架构师,编写大量的Linux代码,并负责在gerrit上review其他同事的代码。Barry Song是Li...
  • juS3Ve
  • juS3Ve
  • 2017年11月14日 00:00
  • 471

linux 性能测评 火焰图

System介绍: 主要用于诊断性能问题 systemtap介绍文章:https://www.ibm.com/developerworks/cn/linux/l-systemtap/ 官网:https...
  • wangjin2891
  • wangjin2891
  • 2016年01月21日 15:47
  • 1365

Linux下用火焰图进行性能分析

CSDN GitHub Linux下用火焰图进行性能分析 LDD-LinuxDeviceDrivers/study/debug/tools/perf/flame_graph 本作品采用知识共...
  • gatieme
  • gatieme
  • 2017年12月24日 17:12
  • 478

宋宝华:LEP(Linux易用剖析器) 是什么,为什么以及怎么办(1)

LEP(LINUX EASY PROFILING) 是Linuxer之LEP项目组(Barry Song,Mac Xu,陈松等以及陈莉君老师)正在致力于打造的一个开源项目,这是LEP文档《LEP是什么...
  • juS3Ve
  • juS3Ve
  • 2017年09月29日 00:00
  • 790

性能分析之使用perf生产火焰图

perf是由Linux Kernel提供的动态追踪调试工具,我们可以使用perf对运行时的程序进行分析 相比单纯依赖log,core进行离线排查,perf是一种在线的调试手段,可以在线上随时进行采样...
  • Ashinee
  • Ashinee
  • 2017年09月18日 17:03
  • 420

在centos linux 环境下使用火焰图

火焰图是个比较方便查看程序资源占用的图形,由于其外表看起来像一团火焰,故命名为火焰图(http://www.brendangregg.com/flamegraphs.html)...
  • molingduzun123
  • molingduzun123
  • 2017年08月21日 16:54
  • 754

生成RGW的火焰图

最近通过perf在分析Ceph对象存储RGW的性能,趁机也生成了一个Flame Graph,可以更直观的帮助我们找到RGW I/O各部分的耗时。先上图,生成的图本来是svg格式的(可以用浏览器打开,并...
  • scaleqiao
  • scaleqiao
  • 2016年06月27日 13:28
  • 1900

JAVA性能分析之使用火焰图

随着业务的发展,使用接口提供的服务的业务越来越多,不同的业务对调用耗时的要求不同,当然,耗时越少越好。而近来已经有三四个调用方反映接口调用耗时太不稳定,代码上的优化已经做了很多,有效果,但还不够。同时...
  • c395318621
  • c395318621
  • 2017年02月15日 22:29
  • 2929

在Linux上生成java程序的火焰图

首先安装perf-map-agent,这个比较麻烦,执行如下: mkdir /usr/lib/jvm cd /usr/lib/jvm yum install git git clone –d...
  • human8848
  • human8848
  • 2017年05月18日 13:03
  • 892

Linux下perf性能测试火焰图只显示函数地址不显示函数名的问题

Linux下perf性能测试火焰图只显示函数地址不显示函数名的问题   最近在centos机器上安装perf对代码做性能测试。百度了一通,使用yum install perf* 这个命令就可以了,结果...
  • u013928720
  • u013928720
  • 2016年12月26日 17:16
  • 934
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:宋宝华:火焰图:全局视野的Linux性能剖析
举报原因:
原因补充:

(最多只允许输入30个字)