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

2023-11-01 17:09:01 浏览数 (1)

在分析性能问题时,我们有两种简单而又行之有效的分析方法。第一种是基于资源视角的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)

0 人点赞