火焰图生成与分析

火焰图是分层数据的可视化,可以直观分析函数的调用频次,函数调用栈,以此来分析性能瓶颈。

1、火焰图简介

1.1、火焰图的分析

  • 每一列代表一个调用栈(栈帧),每一个格子代表调用栈中的一个函数。
  • 横轴:全部的采样样本的数量。格子的宽度代表函数调用频次,一个格子的宽度越大,越说明其可能是瓶颈原因。火焰图从左到右并不代表时间流动,只是按照字母顺序排列,将栈中同一层的函数最大化合并,实现信息的聚合
  • 纵轴:函数调用栈的深度(栈桢数)。按照函数调用关系从下到上排列。最顶上格子代表采样时,正在占用 CPU 的函数。
  • 颜色:默认采用随机暖色调对函数栈帧进行着色。也可以通过色调表示代码的类型(红色:原生用户态代码,橙色:内核态代码等),背景颜色表示火焰图的类型(黄色:on-cpu,蓝色:off-cpu,绿色:内存火焰图等)

阅读火焰图,应该先找到最宽的部分并去理解它。

1.2、火焰图局限性

  • 掉栈不完整
  • 函数名缺失

先不要做编译优化,很多函数优化后,看不到调用栈

1.3、火焰图的类型

on-cpu 火焰图

分析 CPU 占用的性能问题。以固定频率采样 CPU 调用栈。横轴表示 cpu 占用时间,纵轴表示调用栈。

off-cpu 火焰图

分析 IO 阻塞,锁竞争,死锁的性能问题。以固定频率采样阻塞事件调用栈。横轴表示阻塞时间,纵轴表示调用栈。

Hot / Cold火焰图

综合 on-cpu 火焰图和 off-cpu 火焰图,分析 cpu 占用和阻塞的场景。

内存火焰图

分析内存泄漏问题,内存占用高的对象。有四种方式:跟踪 malloc/free,跟踪 brk,跟踪 mmap,跟踪页错误。横轴表示内存申请或释放的函数调用次数,纵轴表示调用栈。

红蓝分叉火焰图

分析不同版本的性能差异问题。对比两个版本的 on-cpu 火焰图。红色表示性能上升,蓝色表示性能下降。

2、绘制火焰图

2.1、火焰图生成流程

  • 采集堆栈:使用 perf/systemtap/dtrace 等工具抓取程序的运行堆栈
  • 折叠堆栈:使用 stackcollapse 程序,对堆栈信息进行分析组合,将重复的堆栈累计在一起,体现出负载和关键路径
  • 生成火焰图:分析 stackcollapse 输出的堆栈信息生成火焰图

2.2、安装火焰图工具

2.2.1、安装 FlameGraph 脚本

FlameGraph 是一套生成火焰图的脚本。

# 下载 FlameGraph
git clone https://gitee.com/mirrors/FlameGraph.git

# 查看帮助
./FlameGraph/flamegraph.pl -h

对于不同的 trace 工具,抓取到的信息不同,对应不同的 stackcollapse 工具。参考官网文档:FlameGraph

2.2.2、安装 perf 命令

系统级性能优化通常包括两个阶段:

  • 性能剖析:寻找性能瓶颈,查找引发性能问题的原因和热点代码。
  • 代码优化:针对具体性能问题而优化代码或编译选项,以及改善软件性能。

perf 命令:返回 CPU 正在执行的函数名以及调用栈,是 Linux 系统原生提供的性能分析工具。

工作原理:固定频率采样 cpu,对 cpu 产生中断,统计函数(或进程 pid)的运行时间,获得 cpu 占用率。

在这里插入图片描述

安装 perf 命令

# 安装 perf 命令
sudo apt install linux-tools-common

# 测试 perf 命令是否可用
sudo perf record -F 99 -a -g -- sleep 10

# 帮助文档
perf -h

常用的 perf 命令

# 查看当前软硬件环境支持的性能事件
perf list
# 分析指定程序的性能概况
perf stat
# 实时显示系统/进程的性能统计信息
perf top
# 记录一段时间内系统/进程的性能事件
perf record
# 读取 perf record 生成的 perf.data 文件,并显示分析数据
perf report:

生成火焰图的采集命令

# 记录一段时间内系统/进程的性能事件
perf record
-e '指定性能事件,默认采集 cycles (cpu clock)
-F '采集频率,每秒采样 n 次
-g '开启 call-graph (stack chain/backtrace) 记录
-o '指定输出文件 output.data,默认输出到perf.data
-p '指定待分析进程的 pid
-t '指定待分析线程的 tid

2.3、例:生成火焰图

2.3.1、采集堆栈

通过 topps -ef | grep 进程名来查看测试的 pid,使用 perf record 采集系统事件

sudo perf record -F 99 -p 46242 -g -- sleep 30

为了便于阅读,perf record 命令可以统计每个调用栈出现的百分比, 然后从高到低排列

perf report -n --stdio
2.3.2、折叠堆栈

使用 perf script 工具对 perf.data 进行解析

perf script -i perf.data &> perf.unfold

用 stackcollapse-perf.pl 将 perf 解析出的内容 perf.unfold 中的符号进行折叠

./FlameGraph/stackcollapse-perf.pl perf.unfold &> perf.folded
2.3.3、生成火焰图

生成 svg 图

./FlameGraph/flamegraph.pl perf.folded > test_oncpu.svg

使用管道简化命令

perf script | ./FlameGraph/stackcollapse-perf.pl | ./FlameGraph/flamegraph.pl > test_oncpu.svg

3、实践:ZeroMQ REQ-REP模型测试

3.1、安装 ZMQ

# 安装必备的库
sudo apt-get install libtool 
sudo apt-get install pkg-config 
sudo apt-get install build-essential
sudo apt-get install autoconf
sudo apt-get install automake

# 安装加密库
git clone https://github.com/jedisct1/libsodium.git
cd libsodium
./autogen.sh -s
./configure && make check
sudo make install
sudo ldconfig

# 安装 libzmq
git clone https://github.com/zeromq/libzmq.git
cd libzmq
git tag
git checkout v4.3.4
./autogen.sh
./configure && make check
sudo make install
sudo ldconfig

3.2、on-cpu火焰图

# 采集数据
perf record -F 99 -p 135989 -g -- sleep 60
# 生成火焰图
perf script | ./FlameGraph/stackcollapse-perf.pl | ./FlameGraph/flamegraph.pl > zeromq-req-rep.svg

3.3、off-cpu 火焰图

使能 sched_schedstats 统计

echo 1 > /proc/sys/kernel/sched_schedstats

通过 perf 采集下列事件

  • sched:sched_stat_sleep:进程主动放弃 cpu 而进入睡眠的等待事件
  • sched:sched_switch:进程由于 I/O 和锁阻塞等原因被调度器切换而进入睡眠的等待事件
  • sched:sched_process_exit:进程的退出事件
perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -p 114143 -g -o perf.data.raw sleep 30
perf inject -v -s -i perf.data.raw -o perf.data

生成火焰图

perf script -F comm,pid,tid,cpu,time,period,event,ip,sym,dso,trace | awk '
    NF > 4 { exec = $1; period_ms = int($5 / 1000000) }
    NF > 1 && NF <= 4 && period_ms > 0 { print $2 }
    NF < 2 && period_ms > 0 { printf "%s\n%d\n\n", exec, period_ms }' | \
    ./FlameGraph/stackcollapse.pl | \
    ./FlameGraph/flamegraph.pl --countname=ms --title="Off-CPU Time Flame Graph" --colors=io > zeromq-req-rep1-offcpu.svg

4、实践:Nginx HTTP

4.1、wrk 压测

安装 HTTP 压测工具:wrk

git clone https://github.com/wg/wrk
cd wrk
make
sudo cp wrk /usr/local/bin

wrk 命令参数

-c	--connections	N	跟服务器建立并保持的TCP连接数量
-d	--duration	    T	压测时间
-t	--threads	    N	使用多少个线程进行压测
-s	--script	    S	指定Lua脚本路径
-H	--header	    H	为每一个HTTP请求添加HTTP头
--latency				在压测结束后,打印延迟统计信息
--timeout		    T	超时时间
-v	--version			打印正在使用的wrk的详细版本信息

使用 wrk 压测

wrk -c 20 -t 2 -d 5M --latency http://192.168.88.136

4.2、on-cpu火焰图

# 查找 nginx worker 进程 pid
ps -ef | grep nginx

# 采集数据
perf record -F 99 -p 1996  -g -- sleep 60

# 生成火焰图
perf script | ./FlameGraph/stackcollapse-perf.pl | ./FlameGraph/flamegraph.pl > nginx-on-cpu.svg

4.3、off-cpu 火焰图

# 查找 nginx worker 进程 pid
ps -ef | grep nginx

# 采集数据
perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -p 1997 -g -o perf.data.raw sleep 30 
perf inject -v -s -i perf.data.raw -o perf.data

# 生成火焰图
perf script -F comm,pid,tid,cpu,time,period,event,ip,sym,dso,trace | awk '
    NF > 4 { exec = $1; period_ms = int($5 / 1000000) }
    NF > 1 && NF <= 4 && period_ms > 0 { print $2 }
    NF < 2 && period_ms > 0 { printf "%s\n%d\n\n", exec, period_ms }' | \
    ./FlameGraph/stackcollapse.pl | \
    ./FlameGraph/flamegraph.pl --countname=ms --title="Off-CPU Time Flame Graph" --colors=io > nginx-off-cpu.svg

5、实践:测试线程池队列

5.1、on-cpu火焰图

# 采集数据
perf record -F 99 -p 42901 -g -- sleep 60

# 生成火焰图
perf script | ./FlameGraph/stackcollapse-perf.pl | ./FlameGraph/flamegraph.pl > threadpool-oncpu.svg

5.2、off-cpu 火焰图

# 使能 sched_schedstats 统计
echo 1 > /proc/sys/kernel/sched_schedstats

# 采集数据
perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -p 8657 -g -o perf.data.raw sleep 30
perf inject -v -s -i perf.data.raw -o perf.data

# 生成火焰图
perf script -F comm,pid,tid,cpu,time,period,event,ip,sym,dso,trace | awk '
    NF > 4 { exec = $1; period_ms = int($5 / 1000000) }
    NF > 1 && NF <= 4 && period_ms > 0 { print $2 }
    NF < 2 && period_ms > 0 { printf "%s\n%d\n\n", exec, period_ms }' | \
    ./FlameGraph/stackcollapse.pl | \
    ./FlameGraph/flamegraph.pl --countname=ms --title="Off-CPU Time Flame Graph" --colors=io > threadpool-offcpu.svg

参考:

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值