前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TSA方法:基于线程时间分布分析性能瓶颈

TSA方法:基于线程时间分布分析性能瓶颈

作者头像
AshinZ
发布2023-11-01 17:09:01
3030
发布2023-11-01 17:09:01
举报

在分析性能问题时,我们有两种简单而又行之有效的分析方法。第一种是基于资源视角的USE方法,通过一系列的检查清单来帮助发现瓶颈和错误;第二种方法就是本文要介绍的基于线程视角的TSA方法。和USE方法一样,TSA方法提供了分析问题的起点,帮助我们缩小问题的区域。这种方法可以用在所有的操作系统上,因为TSA方法的出发点很明确:线程的时间都花在哪里了?

TSA方法

TSA(Thread State Analysis)方法可以被概括成如下的两个步骤:

  • 对于每个感兴趣的线程,衡量线程在不同状态下的总时间;
  • 使用适当的工具按最频繁到最不频繁的顺序分析线程的状态;

分析步骤

这里线程可以指代操作系统可以运行的任何实体,不管是线程、任务还是进程。

状态

线程有多种状态,通常来说我们可以关注如下的六种比较通用的状态:

  • 执行(Executing):在CPU上运行;
  • 可执行(Runnable):等待被调度到CPU上运行;
  • 匿名换页(Anonymous Paging):可运行,因为等待匿名换页而被阻塞;
  • 睡眠(Sleeping):等待I/O
  • 锁(Lock):等待拿锁状态;
  • 空闲(Idle):等待任务;

线程状态

除了这些比较通用的状态,对于可以简单的获取并且很有用的附加状态,我们也可以将它们加入到考虑中。

状态分析

我们通过下表展示每种状态的含义和针对每种状态的分析方法:

TSA分析方法 - https://www.brendangregg.com/tsamethod.html

简单来说,对于每种状态都有不同的分析思路:

  • 线程大部分的时间在运行态:将运行时间划分为用户态运行时间和内核运行时间。对于用户态运行时间,通过CPU采样来寻找程序热点;对于内核态运行时间,通过观察系统调用和对内核做采样来寻找热点;
  • 线程大部分时间在可运行状态:检查CPU的利用率和饱和度,看看是否有超载的情况存在。此外,检查是否有绑核;
  • 线程大部分时间在匿名换页阶段:检查系统主存的可用情况,看看是否有资源限制,并且检查分页和换页情况;
  • 线程大部分时间在睡眠状态:检查系统调用、资源使用情况和线程阻塞;
  • 线程大部分时间在等待锁:确定线程正在等待锁,并且分析获取锁等待的原因;
  • 线程大部分状态在闲置状态:检查应用的客户端负载;
状态转移

下面是这些状态的转移图:

线程状态转移

空闲状态

一般来说,我们没有什么简单的方法来识别空闲的情况。线程可能因为各种原因而在等待运行,此时从内核的角度来看,应用线程处在睡眠或者等待锁阶段,但事实上这个线程可能是处于空闲状态。因此一般情况下,我们可以在分析中跳过空闲状态的分析,我们需要调查空闲状态之后的最常见状态。

延时状态

我们可以用延迟指标来衡量可运行、匿名换页、睡眠和锁等待状态,通过优化延时,我们可以减少这些状态的时间,甚至将这些状态的时间缩减为0,这种情况下,就可以减少分析的难度,从而更快的进行分析。因此,如果线程有比较多的时间在可运行或者匿名换页状态,我们可以尝试先调整并消除这些状态。

添加其他状态

我们前面说的六种状态是最通用的状态,我们可以尝试将它们做更近一步的划分。添加状态可以帮助我们更清晰的了解线程在干什么。比如我们可以做如下的细分:

  • 将执行状态分为用户态执行状态和内核态执行状态;
  • 将睡眠状态根据其原因分为因为存储睡眠、网络睡眠还是其他原因睡眠等多种状态;

在实际的状态添加过程中,可能会有一些困难。例如如何衡量睡眠状态的多种子状态消耗的时间。

使用例子

下面我们会通过一个简短的例子来分析云计算中常见的性能问题,并展示在这个过程中TSA方法是如何为我们寻找方向的。

我们假设某个应用存在性能问题。遵循TSA方法,我们测量线程在六种状态下持续的时间。我们发现有大约50%的时间在Runnable状态,也即等待被调度到CPU上运行的状态。基于这个信息,我们将分析方向先放在CPU上。我们可以使用查看CPU是否过载的mpstat命令来观察CPU是否超载。很快我们可能会发现应用程序的性能瓶颈在CPU资源限制上,这可能是因为在云计算场景中资源会被限制。因此我们尝试提高CPU资源限制,就可能会提高性能。

TSA分析例子

pidstat

在原文中,Gregg介绍了Solaris 系统中的prstat命令来作为使用TSA方法的工具:

prstat

Linux中,没有该工具,笔者认为可以尝试通过pidstat来协助我们进行分析:

代码语言:javascript
复制
pidstat -p 34653 -udhr

这是pidstat一些常用的选项:

  • -u:显示CPU使用率、用户空间和内核空间进程的使用率、上下文切换次数、中断次数等信息。
  • -r:显示内存使用率、虚拟内存大小、物理内存大小、缺页错误次数等信息。
  • -d:显示磁盘I/O使用率、读写速度、I/O操作次数等信息。
  • -t:显示进程的线程信息。
  • -h:以人类可读的格式显示输出结果。
  • -p:指定进程pid

结果如下图:

以下是对应指标的含义:

  • %CPU:进程使用CPU时间的百分比、
  • %usr:用户空间进程占用CPU时间的百分比
  • %system:内核空间进程占用CPU时间的百分比
  • %guest:运行虚拟机的时间占用CPU时间的百分比
  • %wait:等待I/O完成的时间占用CPU时间的百分比
  • %CPU:进程使用CPU时间的百分比
  • minflt/s:每秒钟发生的次缺页错误(minor page faults)的数量
  • majflt/s:每秒钟发生的主缺页错误(major page faults)的数量
  • VSZ:进程使用的虚拟内存大小(单位为KB)
  • RSS:进程使用的物理内存大小(单位为KB)
  • %disk read:进程从磁盘读取数据的时间占用CPU时间的百分比
  • %disk write:进程向磁盘写入数据的时间占用CPU时间的百分比
  • KB_rd/s:每秒钟从磁盘读取的数据量(单位为KB)
  • KB_wr/s:每秒钟向磁盘写入的数据量(单位为KB)
  • KB_ccwr/s:每秒钟向磁盘写入的数据量,但是被缓存了(单位为KB)
  • iodelay:I/O操作的平均延迟时间(单位为毫秒)
  • Command:进程的名称

基于pidstat我们可以初步的做一些分析,查看进程的时间主要花在哪里。更进一步的分析则需要使用更多的工具进行分析。

结论

TSA方法告诉我们分析性能问题时,可以去了解线程的时间主要花在哪里,然后进行更进一步的分析。其出发点和USE方法大体一致,也即先了解系统上正在发生什么,再去进行针对性的分析,只不过两者的视角并不一致。

参考资料

  • TSA Method(https://www.brendangregg.com/tsamethod.html)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-08-12,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • TSA方法
  • 状态
    • 状态分析
      • 状态转移
        • 空闲状态
          • 延时状态
            • 添加其他状态
            • 使用例子
            • pidstat
            • 结论
            • 参考资料
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档