Linux 是怎么计算 CPU 使用率统的

相关概念

在 Linux 执行 top 时可以查看 CPU 使用的情况其中会包含 8 个模块

CPU 占用率相关概念

  • 用户时间(User time): 表示 CPU 执行用户进程的时间,包括 nices 时间。通常期望用户空间 CPU 越高越好。
  • 系统时间(System time): 表示 CPU 在内核运行时间,包括 IRQ 和 softirq 时间。系统 CPU 占用率高,表明系统某部分存在瓶颈。通常值越低越好。
  • 等待时间(Waiting time) : CPU 在等待 I/O 操作完成所花费的时间。系统不应该花费大量时间来等待 I/O 操作,否则就说明 I/O 存在瓶颈。
  • 空闲时间(Idle time) : 系统处于空闲期,等待进程运行。
  • Nice 时间(Nice time) : 系统调整进程优先级所花费的时间。
  • 硬中断处理时间(Hard Irq time) : 系统处理硬中断所花费的时间。
  • 软中断处理时间(SoftIrq time) : 系统处理软中断中断所花费的时间。
  • 丢失时间(Steal time) : 被强制等待(involuntary wait)虚拟 CPU 的时间,此时 hypervisor 在为另一个虚拟处理器服务。

top 命令看到的 CPU 占用率信息及各项值含义

%Cpu(s):  0.7 us,  0.7 sy,  0.0 ni, 98.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
  • us: User time 用户态使用的 cpu 时间比。CPU 一共花了多少比例的时间运行在用户态空间或者说是用户进程 running user space processes。典型的用户态空间程序有:Shell、数据库、web 服务器。
  • sy: System time 系统态使用的 cpu 时间比。System 的含义与 User 相似。System 表示:CPU 花了多少比例的时间在内核空间运行。分配内存、IO 操作、创建子进程……都是内核操作。这也表明,当 IO 操作频繁时,System 参数会很高。
  • ni: Nice time用做 nice 加权的进程分配的用户态 cpu 时间比。用户空间进程的 CPU 的调度优先级,范围为[-20,19]。每个 linux 进程都有个优先级,优先级高的进程有优先执行的权利,这个叫做 pri。进程除了优先级外,还有个优先级的修正值。即比如你原先的优先级是 20,然后修正值为-2,那么你最后的进程优先级为 18。这个修正值就叫做进程的 nice 值。
  • id: Idle time 空闲的 cpu 时间比。一般而言,idel + user + nice 约等于 100%。
  • wa: Waiting time CPU 等待磁盘写入完成时间。在计算机中,读写磁盘的操作远比 CPU 运行的速度要慢,CPU 负载处理数据,而数据一般在磁盘上需要读到内存中才能处理。当 CPU 发起读写操作后,需要等着磁盘驱动器将数据读入内存,从而导致 CPU 在等待的这一段时间内无事可做。CPU 处于这种等待状态的时间由 Wait 参数来衡量。所以如果一台机器看到 wa 特别高,那么一般说明是磁盘 IO 出现问题。
  • hi: Hard Irq time 硬中断消耗时间
  • si: SoftIrq time 软中断消耗时间 如果程序都没什么问题,那么是没有 hisi 的,但是实际上有个硬中断和软中断的概念。比如硬中断,CPU 在执行程序的时候,突然外设硬件(比如硬盘出现问题了)机器需要立刻通知 cpu 进行现场保存工作。这个时候会 CPU 会出现上下文切换。就是 CPU 会有一部分时间会被硬中断占用了,这个时间就是hi。相类似,si是软中断的 cpu 占用时间,软中断是由软件的指令方式触发的。
  • st: Steal time 虚拟机偷取时间。对虚拟机来说的,一台物理是可以虚拟化出几台虚拟机的。在其中一台虚拟机上用 top 查看发现st不为 0,就说明本来有这么多个 CPU 时间是安排给这个虚拟机的,但是由于某种虚拟技术,把这个 CPU 时间分配给了其他的虚拟机了。这就叫做偷取。

计算方式

Linux CPU 占用率计算,都是根据/proc/stat 文件内容计算而来。

cpu  6828152 1527 6543411 876011091 668088 0 36573 0 0 0
cpu0 6828152 1527 6543411 876011091 668088 0 36573 0 0 0
intr 1389849603 100 412 0 0 1170 0 3 0 0 0 0 34 15 0 0 0 0 0 0 0 0 0 0 0 1 16894685 273 0 22 0 7167543 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 20567153704
btime 1568117559
processes 229626
procs_running 6
procs_blocked 0
softirq 592769402 2 371814856 428995 53078902 0 0 136720 0 0 167309927

总结

  • Linux CPU 占用率是根据/proc/stat 文件中的数据计算而来
  • /proc/stat 中的数据精度为 ticks,即 1/HZ 秒
  • 内核每个 ticks 会更新一次 CPU 使用信息
  • CPU 占用率的精度为 1/HZ 秒

参考资料

1. Understanding CPU Steal Time - when should you be worried? 2. Understanding Linux CPU Load - when should you be worried? 3. Slow Server? This is the Flow Chart You’re Looking For 4 . https://scoutapm.com/blog/restricting-process-cpu-usage-using-nice-cpulimit-and-cgroups