Linux下⽤⽕焰图进⾏性能分析
CSDN GitHub
本作品采⽤进⾏许可, 转载请注明出处, 谢谢合作
因本⼈技术⽔平和知识⾯有限, 内容如有纰漏或者需要修正的地⽅, 欢迎⼤家指正, 也欢迎⼤家提供⼀些其他好的调试⼯具以供收录, 鄙⼈在此谢谢啦
软件的性能分析, 往往需要查看 CPU 耗时, 了解瓶颈在哪⾥.
⽕焰图(flame graph) 是性能分析的利器
1 ⽕焰图简介
很多⼈感冒发烧的时候, 往往会模仿神农⽒尝百草的路⼦: 先尝尝抗病毒的药, 再试试抗细菌的药, 甭管家⾥有什么药挨个试, 什么中药西药,
瞎猫总会碰上死耗⼦, 如此做法⾃然是不可取的, 正确的做法应该是去医院验个⾎, 确诊后再对症下药.
让我们回想⼀下我们⼀般是如何调试程序的 : 通常是在没有数据的情况下依靠主观臆断来瞎蒙, ⽽不是考
虑问题到底是什么引起的!
毫⽆疑问, 调优程序性能问题的时候, 同样需要对症下药. 好消息是 发明了
1.1 ⽕焰图
常见的⽕焰图类型有 , , 还有 , , 等等.
关于⽕焰图详细的介绍可以参考 , 简⽽⾔之 : 整个图形看起来就像⼀团跳动的⽕焰, 这也正是其名字的由来. 燃烧在⽕苗尖部的就是 CPU 正在执⾏的操作, 不过需要说明的是颜⾊是随机的, 本⾝并没有特殊的含义, 纵向表⽰调⽤栈的深度, 横向表⽰消耗的时间. 因为调⽤栈在横向会按照字母排序, 并且同样的调⽤栈会做合并, 所以⼀个格⼦的宽度越⼤越说明其可能是瓶颈. 综上所述, 主要就是看那些⽐较宽⼤的⽕苗, 特别留意那些类似平顶⼭的⽕苗.
要⽣成⽕焰图, 必须要有⼀个顺⼿的 ⼯具, 如果操作系统是 Linux 的话, 那么选择通常是 , 中的⼀种. 其中 perf 相对更常⽤, 因为它时 Linux Kernel 内置的性能调优⼯具, 多数 Linux 都包含了它, 有兴趣的读者稍后可以参考 中的介绍, 尤其是⾥⾯关于如何处理 Broken stacks 问题的描述, 建议多看⼏遍, ⽽ systemtap 相对更强⼤, 不过缺点是你需要先学会它本⾝的编程语⾔.
早期⽕焰图在 Nginx 和 社区⽐较活跃, 如果你是⼀个 Nginx 开发或者优化⼈员, 那么我强烈推荐你使⽤
的 , 乍⼀看名字你可能会误以为这个⼯具包是 nginx 专⽤的, 实际上这⾥⾯很多⼯具适⽤于任何 C/CPP 语⾔编写的程序:
程序功能
⽤来⽣成 On-CPU ⽕焰图的采样数据()
⽤来⽣成 Off-CPU ⽕焰图的采样数据 ()svg图
1.2 On/Off-CPU ⽕焰图
那么什么时候使⽤ On-CPU ⽕焰图? 什么时候使⽤ Off-CPU ⽕焰图呢?
取决于当前的瓶颈到底是什么, 如果是 CPU 则使⽤ On-CPU ⽕焰图, 如果是 IO 或锁则使⽤ Off-CPU ⽕焰图. 如果⽆法确定, 那么可以通过压测⼯具来确认 : 通过压测⼯具看看能否让 CPU 使⽤率趋于饱和, 如果能那么使⽤ On-CPU ⽕焰图, 如果不管怎么压, CPU 使⽤率始终上不来, 那么多半说明程序被 IO 或锁卡住了, 此时适合使⽤ Off-CPU ⽕焰图.
如果还是确认不了, 那么不妨 On-CPU ⽕焰图和 Off-CPU ⽕焰图都搞搞, 正常情况下它们的差异会⽐较⼤, 如果两张⽕焰图长得差不多, 那么通常认为 CPU 被其它进程抢占了.
在采样数据的时候, 最好通过压测⼯具对程序持续施压, 以便采集到⾜够的样本. 关于压测⼯具的选择, 如果选择 ab 的话, 那么务必记得开启-k 选项, 以避免耗尽系统的可⽤端⼝. 此外, 我建议尝试使⽤诸如 之类更现代的压测⼯具.
1.3 ⽕焰图可视化⽣成器
Brendan D. Gregg 的 Flame Graph ⼯程实现了⼀套⽣成⽕焰图的脚本.
Flame Graph 项⽬位于 GitHub上
⽤ git 将其 clone下来
git clone github/brendangregg/FlameGraph.git
⽣成和创建⽕焰图需要如下⼏个步骤
流程描述脚本
捕获堆
栈
使⽤ perf/systemtap/dtrace 等⼯具抓取程序的运⾏堆栈perf/systemtap/dtrace
折叠堆栈trace ⼯具抓取的系统和程序运⾏每⼀时刻的堆栈信息, 需要对他们进⾏分析组合, 将重复的堆栈累计在⼀起,
从⽽体现出负载和关键路径
FlameGraph 中的
stackcollapse 程序
⽣成⽕
焰图
分析 stackcollapse 输出的堆栈信息⽣成⽕焰图flamegraph.pl 不同的 trace ⼯具抓取到的信息不同, 因此 Flame Graph 提供了⼀系列的 stackcollapse ⼯具.
stackcollapse描述
stackcollapse.pl for DTrace stacks
stackcollapse-perf.pl for Linux perf_events “perf script” output
stackcollapse-pmc.pl for FreeBSD pmcstat -G stacks
stackcollapse-stap.pl for SystemTap stacks
stackcollapse-instruments.pl for XCode Instruments
stackcollapse-vtune.pl for Intel VTune profiles
stackcollapse-ljp.awk for Lightweight Java Profiler
stackcollapse-jstack.pl for Java jstack(1) output
stackcollapse-gdb.pl for gdb(1) stacks
stackcollapse-go.pl for Golang pprof stacks
stackcollapse-vsprof.pl for Microsoft Visual Studio profiles
2 ⽤ perf ⽣成⽕焰图
2.1 perf 采集数据
让我们从 perf 命令(performance 的缩写)讲起, 它是 Linux 系统原⽣提供的性能分析⼯具, 会返回 CPU 正在执⾏的函数名以及调⽤栈(stack)
sudo perf record -F 99-p 3887-g -- sleep 30
[外链图⽚转存失败,源站可能有防盗链机制,建议将图⽚保存下来直接上传(img-KNgLEYyP-1624459176139)
(./perf_record_chrome.png)]
perf record 表⽰采集系统事件, 没有使⽤ -e 指定采集事件, 则默认采集 cycles(即 CPU clock 周期), -F 99 表⽰每秒 99 次, -p 13204 是进程号, 即对哪个进程进⾏分析, -g 表⽰记录调⽤栈, sleep 30 则是持续 30 秒.
-F 指定采样频率为 99Hz(每秒99次), 如果 99次 都返回同⼀个函数名, 那就说明 CPU 这⼀秒钟都在执⾏同⼀个函数, 可能存在性能问题.
运⾏后会产⽣⼀个庞⼤的⽂本⽂件. 如果⼀台服务器有 16 个 CPU, 每秒抽样 99 次, 持续 30 秒, 就得到 47,520 个调⽤栈, 长达⼏⼗万甚⾄上百万⾏.
为了便于阅读, perf record 命令可以统计每个调⽤栈出现的百分⽐, 然后从⾼到低排列.
sudo perf report -n --stdio
2.2 ⽣成⽕焰图
⾸先⽤ perf script ⼯具对 perf.data 进⾏解析
# ⽣成折叠后的调⽤栈
perf script -i perf.data &> perf.unfold
将解析出来的信息存下来, 供⽣成⽕焰图
⾸先⽤ stackcollapse-perf.pl 将 perf 解析出的内容 perf.unfold 中的符号进⾏折叠 :
# ⽣成⽕焰图
./stackcollapse-perf.pl perf.unfold &> perf.folded
最后⽣成 svg 图
./flamegraph.pl perf.folded > perf.svg
我们可以使⽤管道将上⾯的流程简化为⼀条命令
perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > process.svg
3 解析⽕焰图
最后就可以⽤浏览器打开⽕焰图进⾏分析啦.
3.1 ⽕焰图的含义
⽕焰图是基于 stack 信息⽣成的 SVG 图⽚, ⽤来展⽰ CPU 的调⽤栈。
y 轴表⽰调⽤栈, 每⼀层都是⼀个函数. 调⽤栈越深, ⽕焰就越⾼, 顶部就是正在执⾏的函数, 下⽅都是它的⽗函数.
x 轴表⽰抽样数, 如果⼀个函数在 x 轴占据的宽度越宽, 就表⽰它被抽到的次数多, 即执⾏的时间长. 注意, x 轴不代表时间, ⽽是所有的调⽤栈合并后, 按字母顺序排列的.
⽕焰图就是看顶层的哪个函数占据的宽度最⼤. 只要有 “平顶”(plateaus), 就表⽰该函数可能存在性能问题。
颜⾊没有特殊含义, 因为⽕焰图表⽰的是 CPU 的繁忙程度, 所以⼀般选择暖⾊调.
3.2 互动性
⽕焰图是 SVG 图⽚, 可以与⽤户互动.
⿏标悬浮
⽕焰的每⼀层都会标注函数名, ⿏标悬浮时会显⽰完整的函数名、抽样抽中的次数、占据总抽样次数的百分⽐点击放⼤
在某⼀层点击,⽕焰图会⽔平放⼤,该层会占据所有宽度,显⽰详细信息。
左上⾓会同时显⽰ “Reset Zoom”, 点击该链接, 图⽚就会恢复原样.
搜索
按下 Ctrl + F 会显⽰⼀个搜索框,⽤户可以输⼊关键词或正则表达式,所有符合条件的函数名会⾼亮显⽰.
3.3 局限
两种情况下, ⽆法画出⽕焰图, 需要修正系统⾏为.
调⽤栈不完整
当调⽤栈过深时,某些系统只返回前⾯的⼀部分(⽐如前10层)。
函数名缺失
有些函数没有名字,编译器只⽤内存地址来表⽰(⽐如匿名函数)。
3.4 浏览器的⽕焰图
Chrome 浏览器可以⽣成页⾯脚本的⽕焰图, ⽤来进⾏ CPU 分析.
打开开发者⼯具, 切换到 Performance ⾯板. 然后, 点击"录制" 按钮, 开始记录数据. 这时, 可以在页⾯进⾏各种操作, 然后停⽌"录制".
这时, 开发者⼯具会显⽰⼀个时间轴. 它的下⽅就是⽕焰图.
浏览器的⽕焰图与标准⽕焰图有两点差异 : 它是倒置的(即调⽤栈最顶端的函数在最下⽅); x 轴是时间轴, ⽽不是抽样次数.
4 红蓝分叉⽕焰图
幸亏有了 CPU ⽕焰图(flame graphs), CPU 使⽤率的问题⼀般都⽐较好定位. 但要处理性能回退问题,
就要在修改前后或者不同时期和场景下的⽕焰图之间, 不断切换对⽐, 来出问题所在, 这感觉就是像在太阳系中搜寻冥王星. 虽然, 这种⽅法可以解决问题, 但我觉得应该会有更好的办法.
所以, 下⾯就隆重介绍 红/蓝差分⽕焰图(red/blue differential flame graphs)
4.1 红蓝差分⽕焰图⽰例
上⾯是. 图中使⽤了两种颜⾊来表⽰状态, 红⾊表⽰增长, 蓝⾊表⽰衰减.
这张⽕焰图中各⽕焰的形状和⼤⼩都是和第⼆次抓取的 profile ⽂件对应的 CPU ⽕焰图是相同的. (其中, y 轴表⽰栈的深度, x 轴表⽰样本的总数, 栈帧的宽度表⽰了 profile ⽂件中该函数出现的⽐例, 最顶层表⽰正在运⾏的函数, 再往下就是调⽤它的栈).
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论