文章采集调用(本文的原理机制,如何使用火焰图快速定位性能问题)

优采云 发布时间: 2022-01-19 03:00

  文章采集调用(本文的原理机制,如何使用火焰图快速定位性能问题)

  本文主要分享使用火焰图的技巧,介绍systemtap的原理和机制,如何使用火焰图快速定位性能问题的原因,加深对systemtap的理解。

  让我们回想一下,作为编程新手,我们是如何调整程序的?通常依靠没有数据的主观假设,稍有经验的同学会分两块或一卷调试差异代码。这种定位问题的方法不仅费时费力,而且不具有普遍性。在遇到其他类似的性能问题时,需要反复踩坑填坑,那么如何避免这种情况呢?

  有句话叫:兵欲行善,必先利其器。个人认为,程序员也需要一把“利器”来定位性能问题。就像医生看病人一样,需要依靠专业的医疗工具(如X光片、听诊器等)进行诊断,最终根据患者的检测结果快速准确地定位病因。医疗工具。性能调优工具(如 perf / gprof 等)用于性能调优,就像 X 射线用于患者一样。他们可以查明程序的性能瓶颈。

  但是,常用的性能调优工具perf等只能在单个显示中列出调用堆栈或非分层时间分布,不够直观。这里推荐大家一起使用火焰图,更直观的呈现perf采集等工具的数据。

  初识火焰图

  火焰图(Flame Graph)是由 Linux 性能优化大师 Brendan Gregg 发明的。与所有其他分析方法不同,Flame Graph 从全局角度看待时间分布。它从底部到顶部列出了所有可能的原因 性能瓶颈的调用堆栈。

  

  火焰图的整个图看起来像一个跳动的火焰,这就是它的名字的由来。

  火焰图有以下特点(这里以on-cpu火焰图为例):

  火焰图类型

  常见的火焰图类型有 On-CPU、Off-CPU 以及 Memory、Hot/Cold、Differential 等。它们适合什么样的问题?

  这里笔者主要使用了On-CPU、Off-CPU和Memory火焰图,所以这里只是对这三个火焰图进行对比,欢迎大家补充指正。

  

  火焰图分析技巧的纵轴代表调用栈的深度(栈帧数),用来表示函数之间的调用关系:下面的函数是上面函数的父函数。横轴代表调用频率。网格的宽度越大,就越有可能成为瓶颈。不同类型的火焰图适用于不同的优化场景。例如,on-cpu 火焰图适用于分析 CPU 使用率较高的问题函数,而 off-cpu 火焰图适用于解决阻塞和锁抢占问题。无意义的东西:横序是为了聚合,与函数之间的依赖或调用关系无关;火焰图的各种颜色是为了方便区分,本身并无特殊含义。更多实践:进行性能优化,自觉使用火焰图法。如何绘制火焰图以进行性能调整(如果有时间)?

  要生成火焰图,您必须有一个方便的动态跟踪工具,如果操作系统是 Linux,通常是 perf 或 systemtap 之一。其中,perf相对来说比较常用。大部分Linux系统都收录perf,可以直接使用;SystemTap 在监控方面更强大、更灵活。关于如何使用perf绘制火焰图,网上有很多文章,所以本文将以SystemTap为例。

  SystemTap 是一个动态跟踪工具。它利用探针机制来采集内核或应用程序的运行信息,使您无需修改​​内核和应用程序的代码即可获得丰富的信息,帮助您分析和定位所需的故障排除问题。SystemTap 定义了类似的 DSL 脚本语言,方便用户根据需要自由扩展。但是,与动态跟踪的鼻祖 DTrace 不同,SystemTap 没有驻留的内核运行时。它需要先将脚本编译成内核模块,然后插入内核执行。这也会导致 SystemTap 启动缓慢并依赖于完整的调试符号表。

  使用SystemTap绘制火焰图的主要流程如下:

  本文的演示步骤将基于操作系统Tlinux 2.2

  安装 SystemTap 和 OS 符号调试表

  使用 yum 工具安装 systemtap:

  yum install systemtap systemtap-runtime

  由于systemtap工具依赖于完整的调试符号表,而且生产环境中不同机器的内核版本不同(虽然都是Tlinux2.2版本,但是内核版本之后的次要版本不同,可以通过 uname -a 命令查看)) 所以我们还需要安装 kernel-debuginfo 包和 kernel-devel 包。我在这里安装了这两个依赖包。

  kernel-devel-3.10.107-1-tlinux2-0046.x86_64

kernel-debuginfo-3.10.107-1-tlinux2-0046.x86_64

  根据需要绘制的火焰图类型和工艺类型选择合适的脚本

  使用 SystemTap 统计相关数据,往往需要根据其语法编写脚本,有一定的门槛。好在github上的agentzh开源了他常用的两套SystemTap脚本:openresty-systemtap-toolkit和stapxx,这两套工具集可以覆盖C进程、nginx进程和Openresty进程的大部分性能问题场景。

  我们这里需要绘制off-cpu火焰图,所以使用sample-bt-off-cpu脚本

  生成内核模块

  现在我们已经安装了统计脚本和systemtap,可以正常使用了,但是由于systemtap是通过生成内核模块来统计相关探针的统计信息,而tlinux要求所有运行的内核模块首先到达tlinux平台签名才能运行,所以:

  所以需要先修改off-cpu脚本生成内核模块;然后签署内核模块;最后使用systemtap命令手动运行脚本统计监控数据

  systemtap执行流程如下:

  

  所以我们在这里修改off-cpu stap脚本,让它只完成第四阶段,只生成一个内核模块

  // 在 stap 命令后增加 -p4 参数,告诉systemtap,当前只需要执行到第四阶段

open my $in, "|stap -p4 --skip-badvars --all-modules -x $pid -d '$exec_path' --ldd $d_so_args $stap_args -"

or die "Cannot run stap: $!\n";

  修改后运行脚本生成内核模块

  // -p 8682 是需要监控的进程的进程号

// -t 30 是指会采样30秒

./sample-bt-off-cpu -p 8692 -t 30

  生成的内核模块名称为stap_xxxxx.ko。由于读者无需关心内核模块的签名,本章略过。

  运行内核模块统计

  内核模块签名后,可以使用staprun命令手动运行相关内核模块

  命令:

  // 注意:签名脚本会将生产的内核模块重命名,需要将名字改回去……(脚本bug)

staprun -x {进程号} {内核模块名} > demo.bt

  值得注意的是,被监控的进程必须有一定的systemtap负载才能采集获取相关数据,即采集时也需要有一定的请求量(通常自己构建请求,对过程进行压力测试)

  将统计数据转换为火焰图

  一旦你有了统计数据 demo.bt,你就可以使用火焰图工具来绘制火焰图

  下载FlameGraph,链接:

  命令:

  ./stackcollapse-stap.pl demo.bt > demo.folded

./flamegraph.pl demo.folded > demo.svg

  这给出了 off-cpu 火焰图:

  

  看图说话

  趁热打铁,通过几张火焰图熟悉火焰图的使用方法

  图片来自春歌微博或个人近期定位问题

  On-cpu 火焰图 Apache APISIX QPS 急剧下降问题

  

  Apache APISIX是一款开源的国产高性能API网关。在选型和压测过程中发现,当路由匹配不同场景时,QPS急剧下降。当它的CPU(48核)占用率几乎100%,QPS几千,通过绘制火焰图,发现主要时间花在了一个表插入阶段(lj_cf_table_insert)。分析代码发现表还没有释放。每次路由不匹配,就会插入数据,导致表越来越大。后续插入耗时过长,导致 QPS 下降。

  off-cpu 火焰图 nginx mutex 问题

  

  这是一个 nginx 的 off-cpu 火焰图。我们可以快速锁定到 ngx_common_set_cache_fs_size -> ngx_shmtx_lock -> sem_wait。这个逻辑使用了互斥锁,这使得 nginx 进程的大部分阻塞等待时间都花在了获取锁上。

  代理监控报告断点问题

  

  这是代理的非 CPU 火焰图。它是一个多线程异步事件模型。主线程处理每条消息,多个线程负责配置和传递或监控和报告的职责。目前的问题是监控上报性能差,无法在周期(一分钟)内完成监控数据上报,导致监控断点。通过off-cpu火焰图,我们可以分析出上报线程在使用curl_easy_perform接口收发http监控数据报文时花费了很多时间。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线