火焰图:全局视野的Linux性能剖析
文章背景
CPU被占满了,这时候我们就要去查看是什么进程将服务器的CPU资源占用满了。通常我们会通过
top或者
htop来快速的查看占据CPU最高的那个进程,如下图:
kube-apiserver命令运行的一个进程,该进程的PID为
25633,当然你可能遇到一个服务器上运行有多个服务,想快速知道占用率最高的那几个进程的话,你可以使用以下命令:
ps aux|head -1;ps -aux | sort -k3nr | head -n 10 //查看前10个最占用CPU的进程
ps aux|head -1;ps -aux | sort -k4nr | head -n 10 //查看前10个最占用内存的进程
不知道CPU使用究竟耗时在哪里,不清楚瓶颈在哪里,此时就可以通过
Linux系统的性能分析工具
perf分析,分析其返回的正在消耗CPU的函数以及调用栈。然后可以通过解析
perf采集的数据,渲染到火焰图🔥,就清楚的知道究竟占用系统CPU资源的罪魁祸首了。
perf,该工具是一个相对简单易上手的性能分析工具,是
Performance单词的缩写,通过其
perf的命令选项完成系统事件的采集到解析,我们来简单的认识一下:
linux上的性能分析工具Perf
安装perf
Ubuntu 16.04.6 LTS因此需要先安装perf才能使用,该工具由
linux-tools-common提供,但是它需要安装后面的依赖。
#安装
root@master:~# apt install linux-tools-common linux-tools-4.4.0-142-generic linux-cloud-tools-4.4.0-142-generic -y
root@master:~# perf -v #显示perf的版本
perf version 4.4.167
25633的进程进行采样分析。
调用栈信息:
root@master:~# sudo perf record -F 99 -p 25633 -g -- sleep 30
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.039 MB perf.data (120 samples) ]
perf record表示记录,
-F 99表示每秒99次,
-p 25633是进程号,即对哪个进程进行分析,
-g表示记录调用栈,
sleep 30则是持续30秒,参数信息可以视情况调整。生成的数据采集文件在当前目录下,名称为
perf.data。
perf record命令可以从高到低排列统计每个调用栈出现的百分比,显示结果如下图所示:
root@master:~# sudo perf report -n --stdio
制作火焰🔥图
on-CPU/off-cpu的区别就是一个是用于CPU是性能瓶颈,一个是IO是性能瓶颈,当你不知道当前的服务器的性能瓶颈究竟是什么的时候,你可以使用这两种类型进行对比,通过两种火焰图的差别是比较大的,如果两张火焰图长得差不多, 那么通常认为CPU被其它进程抢占了.
On-CPU 火焰图, 如果不管怎么压, CPU 使用率始终上不来, 那么多半说明程序被
IO 或锁卡住了, 此时适合使用
Off-CPU 火焰图. 你可以通过压测工具进行测试,目前比较常用的就是
ab和
wrk,我建议尝试使用诸如
wrk
[6] 之类更现代的压测工具.
如果选择
ab的话, 那么务必记得开启-k选项, 以避免耗尽系统的可用端口
Github上有Brendan D. Gregg 的 Flame Graph 工程实现了一套生成火焰图的脚本.我们可以直接克隆下来直接用。
cd && git clone https://github.com/brendangregg/FlameGraph.git
-
捕获堆栈: 使用perf捕捉进程运行堆栈信息 -
折叠堆栈: 对抓取的系统和程序运行每一时刻的堆栈信息进行分析组合, 将重复的堆栈累计在一起, 从而体现出负载和关键路径,通过stackcollapse脚本完成 -
生成火焰图:分析 stackcollapse 输出的堆栈信息渲染成火焰图
Flame Graph中提供了抓取不同信息的脚本,可以按需使用。下面我们需要对捕获到的进程堆栈信息
perf.data进行折叠,生成折叠的堆栈信息:
root@master:~# perf script -i /root/perf.data &> /root/perf.unfold
stackcollapse-perf.pl 将 perf 解析出的内容
perf.unfold 中的符号进行折叠
root@master:~/FlameGraph# ls
aix-perf.pl docs example-perf.svg pkgsplit-perf.pl stackcollapse-aix.pl stackcollapse-go.pl stackcollapse-ljp.awk stackcollapse-pmc.pl stackcollapse-vsprof.pl test.sh
demos example-dtrace-stacks.txt files.pl range-perf.pl stackcollapse-bpftrace.pl stackcollapse-instruments.pl stackcollapse-perf.pl stackcollapse-recursive.pl stackcollapse-vtune.pl
dev example-dtrace.svg flamegraph.pl README.md stackcollapse-elfutils.pl stackcollapse-java-exceptions.pl stackcollapse-perf-sched.awk stackcollapse-sample.awk stackcollapse-xdebug.php
difffolded.pl example-perf-stacks.txt.gz jmaps record-test.sh stackcollapse-gdb.pl stackcollapse-jstack.pl stackcollapse.pl stackcollapse-stap.pl test
root@master:~/FlameGraph# ./stackcollapse-perf.pl /root/perf.unfold &> /root/perf.folded
root@master:~/FlameGraph#
root@master:~/FlameGraph# ./flamegraph.pl /root/perf.folded > /root/perf.svg
|将整个过程简化:
cd && perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > process.svg
stack信息生成的
SVG 图片, 用来展示 CPU 的调用栈。
-
y轴表示调用栈, 每一层都是一个函数. 调用栈越深, 火焰就越高, 顶部就是正在执行的函数, 下方都是它的父函数. -
x轴表示抽样数, 如果一个函数在 x 轴占据的宽度越宽, 就表示它被抽到的次数多, 即执行的时间长. 注意, x 轴不代表时间, 而是所有的调用栈合并后, 按字母顺序排列的.
"平顶"(plateaus), 就表示该函数可能存在性能问题。颜色没有特殊含义, 因为火焰图表示的是 CPU 的繁忙程度, 所以一般选择暖色调.
调用栈不完整调用栈过深时,某些系统只返回前面的一部分(比如前10层);当
函数名缺失,函数没有名字,编译器只用内存地址来表示(比如匿名函数),所以使用火焰图也是存在分析不到的地方。你也可以通过以下脚本进行采集分析火焰图:
if [ $# -ne 1 ];then
echo "Usage: $0 seconds"
exit 1
fi
perf record -a -g -o perf.data &
PID=`ps aux| grep "perf record"| grep -v grep| awk '{print $2}'`
if [ -n "$PID" ]; then
sleep $1
kill -s INT $PID
fi
# wait until perf exite
sleep 1
perf script -i perf.data &> perf.unfold
perl stackcollapse-perf.pl perf.unfold &> perf.folded
perl flamegraph.pl perf.folded >perf.svg
参考资料
On-CPU: http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html
[2]Off-CPU: http://www.brendangregg.com/FlameGraphs/offcpuflamegraphs.html
[3]Memory: http://www.brendangregg.com/FlameGraphs/memoryflamegraphs.html
[4]Hot/Cold: http://www.brendangregg.com/FlameGraphs/hotcoldflamegraphs.html
[5]Differential: http://www.brendangregg.com/blog/2014-11-09/differential-flame-graphs.html
[6]wrk: https://github.com/wg/wrk
觉得不错,请点个在看呀
