前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >差分火焰图,让你的代码优化验证事半功倍

差分火焰图,让你的代码优化验证事半功倍

作者头像
AshinZ
发布2023-11-01 17:04:57
3520
发布2023-11-01 17:04:57
举报

在性能分析中,我们常常会用到如下所示的火焰图:

火焰图

一般来说,我们将这种火焰图称为on-cpu火焰图,可以用来记录CPU上运行的程序的占比情况。除此之外,还有多种其他种类的火焰图,如:

  • Memory 火焰图
  • off-cpu火焰图
  • 差分火焰图
  • CPI火焰图

本文我们将介绍差分火焰图。主要介绍以下的内容:

  • 为什么要有差分火焰图
  • 如何生成差分火焰图
  • 差分火焰图的形成原理
  • 开源项目pyroscope

为什么要有差分火焰图?

在性能分析和优化的过程中,我们经常使用使用火焰图;而当一轮优化完成过后,我们需要做回归验证来判断性能是否提升。除了尝试通过诸如延时、qps等指标来判断是否优化成功,我们也可以通过火焰图的热点变化来进行判断。

而当比较两个火焰图的时候,我猜你大概会这么做:

对比火焰图

打开两个标签,横向的比对两个火焰图的区别,这样麻烦且不够精确。因此,我们尝试引入差分火焰图:

差分火焰图-brendangregg.com

差分火焰图是两个火焰图A、B比较之后的结果,我们可以认为是B-A。往往采取红蓝配色,我们也可以称之为是红蓝对比火焰图,其中红色代表增长,蓝色代表减少。例如deflate_slow函数:

defalte_slow变化

这个函数是红色的,说明A火焰图相对于火焰图B,函数deflate_slow的调用变多了18.16%;而蓝色的部分则是相反的,表达A火焰图相较于B火焰图,某函数的调用变少了。

想象一下现在有一个火焰图,我们优化了其中某个调用占比1%的函数,如果采取对比方法,恐怕很难发现,而采取差分火焰图,则能够很快的发现哪里变化了以及变化了多少。

总结:「差分火焰图可以帮助我们快速的进行回归验证,比较两个火焰图的变化。」

如何生成差分火焰图

我们可以用如下的方式生成差分火焰图:

代码语言:javascript
复制
# 第一次Profiling结果
perf record -ag -F 999 -- sleep 20
perf script > A.stacks
# 第二次Profiling结果
perf record -ag -F 999 -- sleep 20
perf script > B.stacks
# 下载FlameGraph仓库
git clone --depth 1 http://github.com/brendangregg/FlameGraph 
# 折叠A.stacks和B.stacks
cd FlameGraph 
./stackcollapse-perf.pl ../A.stacks > A.folded
./stackcollapse-perf.pl ../B.stacks > B.folded
# 基于折叠结果做差
./difffolded.pl A.folded B.folded > diff.folded
# 生成差分火焰图
./flamegraph.pl diff.folded > diff.svg

这里需要读者对火焰图的生成比较熟悉,如果不熟悉的读者可以先了解一下火焰图的生成过程。

差分火焰图的形成原理

在生成差分火焰图的过程中,和生成一般的火焰图不同的一步是我们调用了difffolded.pl对两个折叠后的堆栈文件进行了比对,并生成了比对后的堆栈文件。我们不妨尝试构造两个堆栈数据:

代码语言:javascript
复制
# 堆栈数据1
[root@VM-16-2-centos ~]# cat Atest.folded 
YDService;foo 1000
YDService;other 1000
A;B;C 1000
A;B;D 400
# 堆栈数据2
[root@VM-16-2-centos ~]# cat Btest.folded 
YDService;foo 1000
A;B;C 400
A;B;D 1000

接着对这两个数据进行差分:

代码语言:javascript
复制
[root@VM-16-2-centos ~]# ./FlameGraph/difffolded.pl Atest.folded Btest.folded > diff.folded

查看数据:

代码语言:javascript
复制
[root@VM-16-2-centos ~]# cat diff.folded 
YDService;foo 1000 1000
A;B;D 400 1000
YDService;other 1000 0
A;B;C 1000 400

可以看到,数据格式变成了调用栈 调用次数1 调用次数2的形式。我们将数据生成火焰图看看:

差分火焰图

我们不妨生成一个B数据的火焰图看看:

B数据火焰图

可以看到除了配色,这两个火焰图的结构是完全一致的。我们可以得出一个结论:「差分火焰图以采样数据B为基准」。既然是这样的话,当涉及到回归的时候,我们应当将初始数据作为采样数据B,这样我们的比较基准就是初始数据,这样能够更好的进行比较。

我们再来看配色:

差分火焰图减少的含义

可以看到这里A->B->C这个调用栈的调用次数是减少了25%,那么这个25%是相对什么来说的呢?

我们不妨看原始数据,A->B->C在数据A中出现了1000次,数据B中出现了400次,减少调用了600次。而整体的调用次数是2400,所以这里的减少百分比是相较于所有的采样数据而言的。

看到这里不知道聪明的读者有没有发现一个问题,YDService->other这个调用对比消失了。这是因为我们前文说了差分火焰图是以采样数据B为基准的,如果某个调用栈在B中完全没有出现的话,那我们就无法比对前后的变化。如果想要初步解决这个问题,可以反转顺序来进行比较,也即将采样数据A作为基准,这样就能看到A中有的部分了。因此,在进行回归验证的时候,我们可以考虑进行两次反转的差分,这样更能帮助我们发现变化的地方。

pyroscope

pyroscope是一个开源项目,目前已被grafana收购。其主要做的是持续性的Profiling,能够让我们从时间的维度查看系统上的调用栈信息:

pyrocope

其提供了Diff的功能,可以帮助我们查看某两个时间段内的调用栈变化:

Diff view

如果对该项目有兴趣,可以自行尝试。

参考资料

  • differential-flame-graphs(https://www.brendangregg.com/blog/2014-11-09/differential-flame-graphs.html)
  • pyroscope(https://github.com/grafana/pyroscope)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-06-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程栩的性能优化笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要有差分火焰图?
  • 如何生成差分火焰图
  • 差分火焰图的形成原理
  • pyroscope
  • 参考资料
相关产品与服务
Grafana 服务
Grafana 服务(TencentCloud Managed Service for Grafana,TCMG)是腾讯云基于社区广受欢迎的开源可视化项目 Grafana ,并与 Grafana Lab 合作开发的托管服务。TCMG 为您提供安全、免运维 Grafana 的能力,内建腾讯云多种数据源插件,如 Prometheus 监控服务、容器服务、日志服务 、Graphite 和 InfluxDB 等,最终实现数据的统一可视化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档