程序员肖邦的博客 享受编程和技术所带来的快乐

深入理解Linux的CPU使用率

2018-12-16
肖邦

CPU 使用率是单位时间内 CPU 使用情况的统计,以百分比的方式展示。那么作为最常用也是最熟悉的 CPU 指标,你能说出 CPU 使用率到底是怎么算出来的吗?

理解CPU使用率的含义

首先,Linux 作为一个多任务操作系统,将每个 CPU 的时间片划分为很短的时间片,再通过调度器轮流分配给各个任务,造成多任务同时运行的错觉。

1、CPU时间的含义

  • 为了维护 CPU 时间,Linux 通过事先定义的节拍率触发时间中断,并使用全局变量 jiffies 记录了开机以来的节拍数,每发生一次时间中断,Jiffies 的值就加 1。

  • 节拍率 HZ 是内核的可配选项,不同的系统设置不同的数值,可以通过如下方式查询

    $ grep 'CONFIG_HZ=' /boot/config-$(uname -r)
    CONFIG_HZ=50
    
  • 正因为节拍率 HZ 是内核选项,用户空间程序并不能直接访问。为了方便用户空间程序,内核还提供了一个用户空间节拍率 USER_HZ ,固定值为 100,也就是 10ms。用户空间程序并不需要关心内核中 HZ 被设置成了多少,因为它看到的总是固定值。

2、通过/proc查看CPU时间

Linux 通过 /proc 虚拟文件系统向用户空间提供了系统内部状态的信息,而 /proc/stat 提供的就是系统 CPU 和任务统计信息,如果只关注 CPU 的话,可以执行下面的命令:

$ cat /proc/stat | grep ^cpu
cpu  280580 7407 286084 172900810 83602 0 583 0 0 0
cpu0 144745 4181 176701 86423902 52076 0 301 0 0 0
cpu1 135834 3226 109383 86476907 31525 0 282 0 0 0

每一列的含义不需要记住,需要的时候,查询 man proc 就可以。

  • user(通常缩写为 us),代表用户态 CPU 时间。不包括下面的 nice 时间,但包括了 guest 时间。
  • nice(通常缩写为 ni),代表低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间。
  • system(通常缩写为 sys),代表内核态 CPU 时间。
  • idle(通常缩写为 id),代表空闲时间。注意,不包括等待 IO 的时间。
  • iowait(通常缩写为 wa),代表等待 IO 的 CPU 时间。
  • irq(通常缩写为 hi),代表处理硬中断的 CPU 时间。
  • softirq(通常缩写为 si),代表处理软中断的 CPU 时间。
  • steal(通常缩写为 st),代表当系统运行在虚拟机中的时候,被其他虚拟机占用的 CPU 时间。
  • guest(通常缩写为 guest),代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的 CPU 时间。
  • guest_nice(通常缩写为 gnice),代表以低优先级运行虚拟机的时间。

3、计算CPU使用率

通常所说的 CPU 使用率,就是除了空闲时间外的其他时间占总 CPU 时间的百分比,用公式来表示就是:

CPU 使用率 = 1 - (空闲时间 / 总 CPU 时间)

根据公式我们可以从 /proc/stat 中的数据,很容易计算出 CPU 使用率,也可以计算出每个场景的 CPU 使用率。不过这里的值是开机以来的节拍数累加值,事实上为了计算 CPU 使用率,性能工具一般都会取间隔一段时间的两次值作差,再计算出这段时间内的平均 CPU 使用率,即:

平均CPU使用率 = 1 - (空闲时间new - 空闲时间old) / (总CPU时间new - 总CPU时间old)

查看 Linux 进程的 CPU 使用率,可以根据 /proc/pid/stat,采用同样的方法来进行计算。注意,平时我们不需要手动计算这些值,各种性能分析工具已经帮助我们计算好了。不过需要注意,不同的工具的间隔时间可能不同。比如,top 默认使用 3 秒时间间隔,而 ps 使用的却是进程的整个生命周期。

怎么查看CPU使用率

查看 CPU 使用率的常用工具应该是 top 和 ps,top 和 ps 是最常用的性能分析工具:

  • top 显示了系统总体的 CPU 和内存使用情况,以及各个进程的资源使用情况。
  • ps 则只显示了每个进程的资源使用情况。

top 并没有细分进程的用户态 CPU 和内核态 CPU。可以使用 pidstat工具,命令显示内容包括:

  • 用户态 CPU 使用率
  • 内核态 CPU 使用率
  • 运行虚拟机 CPU 使用率
  • 等待 CPU 使用率
  • 以及总的 CPU 使用率
  • 最后的 Average 部分,还计算了 5 组数据的平均值。

CPU使用率过高怎么办

通过 top、ps、pidstat 等工具找到 CPU 使用率较高的进程,我们接下来想知道,占用 CPU 的到底是代码里的哪个函数呢?perf 工具最适合在第一时间分析进程的 CPU 问题,它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还能分析指定应用程序的性能问题。下边是我最常用的两种方式:

  • perf top,它能够实时显示占用 CPU 时钟最多的函数或指令,因此可以用来查找热点函数。
  • perf record + perf report。record 执行后保存数据信息,report 可以离线或后续分析。

实际使用中,我们还经常为 perf top 和 perf record 加上 -g 参数,开启调用关系的采样,方便我们根据调用链来分析性能问题。

简单案例分析

我们以 Nginx + PHP 的 Web 服务为例,来看看当你发现 CPU 使用率过高的问题后,如何使用 top 等工具找出异常进程,又如何利用 perf 找出引发性能问题的函数。

模拟 Nginx 压力

# 并发 10 个请求测试 Nginx 性能,总共测试 100 个请求
$ ab -c 10 -n 100 http://192.168.0.10:10000/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, 
...
Requests per second:    11.63 [#/sec] (mean)
Time per request:       859.942 [ms] (mean)
...

可以发现 Nginx 的处理能力很差,通过 top 命令分析,得知 php-fpm 进程导致,接下来我们使用 perf 来分析一下具体哪些函数导致 CPU 高。

# -g 开启调用关系分析,-p 指定 php-fpm 的进程号 21515
$ perf top -g -p 21515

通过 perf 分析到耗时严重的函数,再结合源代码进行定位分析,找出问题原因即可。

概念小结

CPU 使用率是最直观和最常用的系统性能指标,更是我们在排查性能问题时,通常会关注的第一个指标。所以我们要搞清楚 user、nice、system、iowait、irq、sortirq 这几种不同 CPU 的使用率,比如说:

  • 用户 CPU 和 Nice CPU 高,说明用户态进程占用了较多的 CPU,所以应该着重排查进程的性能问题。
  • 系统 CPU 高,说明内核态占用了较多的 CPU,所以应该着重排查内核线程或者系统调用的性能问题。
  • IO 等待 CPU 高,说明等待 IO 的时间比较长,所以应该着重排查系统存储是不是出现了 IO 问题。
  • 软中断和硬中断高,说明软中断或硬中断的处理程序占用了较多的 CPU,所以应该着重排查内核中的中断服务程序。

Similar Posts

Comments