前几节里,我通过几个案例,带你分析了各种常见的 CPU 性能问题。通过这些,我相信你对 CPU 的性能分析已经不再陌生和恐惧,起码有了基本的思路,也了解了不少 CPU 性能的分析工具。

不过,我猜你可能也碰到了一个我曾有过的困惑: CPU 的性能指标那么多,CPU 性能分析工具也是一抓一大把,如果离开专栏,换成实际的工作场景,我又该观察什么指标、选择哪个性能工具呢?

不要担心,今天我就以多年的性能优化经验,给你总结出一个“又快又准”的瓶颈定位套路,告诉你在不同场景下,指标工具怎么选,性能瓶颈怎么找。

 

CPU 性能指标


我们先来回顾下,描述 CPU 的性能指标都有哪些。你可以自己先找张纸,凭着记忆写一写;或者打开前面的文章,自己总结一下。

首先,最容易想到的应该是 CPU 使用率,这也是实际环境中最常见的一个性能指标。

CPU 使用率描述了非空闲时间占总 CPU 时间的百分比,根据 CPU 上运行任务的不同,又被分为用户 CPU、系统 CPU、等待 I/O CPU、软中断和硬中断等。

  • 用户 CPU 使用率,包括用户态 CPU 使用率(user)和低优先级用户态 CPU 使用率(nice),表示 CPU 在用户态运行的时间百分比。用户 CPU 使用率高,通常说明有应用程序比较繁忙。
  • 系统 CPU 使用率,表示 CPU 在内核态运行的时间百分比(不包括中断)。系统 CPU 使用率高,说明内核比较繁忙。
  • 等待 I/O 的 CPU 使用率,通常也称为 iowait,表示等待 I/O 的时间百分比。iowait 高,通常说明系统与硬件设备的 I/O 交互时间比较长。
  • 软中断和硬中断的 CPU 使用率,分别表示内核调用软中断处理程序、硬中断处理程序的时间百分比。它们的使用率高,通常说明系统发生了大量的中断。
  • 除了上面这些,还有在虚拟化环境中会用到的窃取 CPU 使用率(steal)和客户 CPU 使用率(guest),分别表示被其他虚拟机占用的 CPU 时间百分比,和运行客户虚拟机的 CPU 时间百分比。

第二个比较容易想到的,应该是平均负载(Load Average),也就是系统的平均活跃进程数。它反应了系统的整体负载情况,主要包括三个数值,分别指过去 1 分钟、过去 5 分钟和过去 15 分钟的平均负载。 

理想情况下,平均负载等于逻辑 CPU 个数,这表示每个 CPU 都恰好被充分利用。如果平均负载大于逻辑 CPU 个数,就表示负载比较重了。 

第三个,也是在专栏学习前你估计不太会注意到的,进程上下文切换,包括:

  • 无法获取资源而导致的自愿上下文切换
  • 被系统强制调度导致的非自愿上下文切换

上下文切换,本身是保证 Linux 正常运行的一项核心功能。但过多的上下文切换,会将原本运行进程的 CPU 时间,消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,缩短进程真正运行的时间,成为性能瓶颈。 

除了上面几种,还有一个指标,CPU 缓存的命中率。由于 CPU 发展的速度远快于内存的发展,CPU 的处理速度就比内存的访问速度快得多。这样,CPU 在访问内存的时候,免不了要等待内存的响应。为了协调这两者巨大的性能差距,CPU 缓存(通常是多级缓存)就出现了。

套路篇:如何迅速分析出系统CPU的瓶颈在哪里?_上下文切换

 就像上面这张图显示的,CPU 缓存的速度介于 CPU 和内存之间,缓存的是热点的内存数据。根据不断增长的热点数据,这些缓存按照大小不同分为 L1、L2、L3 等三级缓存,其中 L1 和 L2 常用在单核中, L3 则用在多核中。

从 L1 到 L3,三级缓存的大小依次增大,相应的,性能依次降低(当然比内存还是好得多)。而它们的命中率,衡量的是 CPU 缓存的复用情况,命中率越高,则表示性能越好。

这些指标都很有用,需要我们熟练掌握,所以我总结成了一张图,帮你分类和记忆。你可以保存打印下来,随时查看复习,也可以当成 CPU 性能分析的“指标筛选”清单。

套路篇:如何迅速分析出系统CPU的瓶颈在哪里?_软中断_02

 

性能工具


掌握了 CPU 的性能指标,我们还需要知道,怎样去获取这些指标,也就是工具的使用。

你还记得前面案例都用了哪些工具吗?这里我们也一起回顾一下 CPU 性能工具。

首先,平均负载的案例。我们先用 uptime, 查看了系统的平均负载;而在平均负载升高后,又用 mpstat 和 pidstat  ,分别观察了每个 CPU 和每个进程 CPU 的使用情况,进而找出了导致平均负载升高的进程,也就是我们的压测工具 stress。

第二个,上下文切换的案例。我们先用 vmstat  ,查看了系统的上下文切换次数和中断次数;然后通过 pidstat ,观察了进程的自愿上下文切换和非自愿上下文切换情况;最后通过 pidstat ,观察了线程的上下文切换情况,找出了上下文切换次数增多的根源,也就是我们的基准测试工具 sysbench。

第三个,进程 CPU 使用率升高的案例。我们先用 top  ,查看了系统和进程的 CPU 使用情况,发现 CPU 使用率升高的进程是 php-fpm;再用 perf top  ,观察 php-fpm 的调用链,最终找出 CPU 升高的根源,也就是库函数 sqrt() 。

第四个,系统的 CPU 使用率升高的案例。我们先用  top 观察到了系统 CPU 升高,但通过 top 和 pidstat  ,却找不出高 CPU 使用率的进程。于是,我们重新审视 top 的输出,又从 CPU 使用率不高但处于 Running 状态的进程入手,找出了可疑之处,最终通过  perf record 和 perf report ,发现原来是短时进程在捣鬼。

另外,对于短时进程,我还介绍了一个专门的工具 execsnoop,它可以实时监控进程调用的外部命令。

最后一个,软中断的案例。我们通过 top 观察到,系统的软中断 CPU 使用率升高;接着查看 /proc/softirqs, 找到了几种变化速率较快的软中断;然后通过 sar 命令,发现是网络小包的问题,最后再用  tcpdump  ,找出网络帧的类型和来源,确定是一个 SYN FLOOD 攻击导致的。

到这里,估计你已经晕了吧,原来短短几个案例,我们已经用过十几种 CPU 性能工具了,而且每种工具的适用场景还不同呢!这么多的工具要怎么区分呢?在实际的性能分析中,又该怎么选择呢?

我的经验是,从两个不同的维度来理解它们,做到活学活用。

活学活用,把性能指标和性能工具联系起来

第一个维度,从 CPU 的性能指标出发。也就是说,当你要查看某个性能指标时,要清楚知道哪些工具可以做到。