CPU usage
我们经常可以通过系统监控工具观察计算机的各种信息,例如在 Linux 下我们常用 top
命令查看具体进程的 CPU 使用率与内存占用率,容我安利一下 bpytop 这个工具,UI 更好看还能自定义,回到正题,内存占用率的计算方式很好理解,就如字面意思,进程所占用的内存大小除以计算机内存的总大小即可得到具体进程的内存占用率,那么 CPU 使用率该如何计算呢?毕竟 CPU 作为一个计算单元并没有所谓容量的概念,既然没有容量,那么对于 CPU 更为重要的就是时间了,进程的 CPU 使用率就是通过进程所占用的 CPU 工作时间计算得来的。
CPU time
From wikipedia:
CPU 时间是指 CPU 用于处理计算机程序或操作系统指令的时间量,而不是经过的时间,其中包括等待输入/输出等 (I/O) 操作或进入低功耗(空闲)模式。
根据 CPU 实际执行的操作,报告的值可以细分为:
- User time,用户时间是 CPU 忙于在 用户空间 中执行代码的时间量。
- System time,系统时间是 CPU 忙于在 内核空间 中执行代码的时间量。
- Idle time,空闲时间是衡量未使用的 CPU 时间量。
- Steal time,窃取时间是衡量虚拟机在特定时间段内被剥夺的 CPU 时间量。
以上是维基百科中对于 CPU 时间的描述,简单来说,若要计算一个进程的 CPU 使用率,计算 CPU 在该进程上花费的时间 除以 CPU 运行的总时间 即可。那么我们要如何获取这些时间呢,这就要涉及到 /proc/stat
了。
/proc
proc 是一个提供内核数据结构接口的伪文件系统(pseudo-filesystem),它通常由系统自动挂载在 /proc
目录下,我们可以通过它获取丰富的系统以及进程信息。在 /proc
下有许多的文件与子文件夹,这里我不一一讨论,可以通过 proc(5) 了解它们的具体作用,这里我们主要讨论 /proc/stat
与 /proc/pid/stat
两个文件。
/proc/stat
/proc/stat
是内核/系统统计数据,其中包括了 CPU 时间等信息,对于计算 CPU 使用率,我们只需要关注 CPU 总时间即可,运行 cat /proc/stat
命令的结果如下所示:
|
|
可以看到运行结果中第一行为 CPU 的总时间,从第二行开始为不同 CPU 核心各自的时间,在多核心的计算机上指令的执行往往会在多个核心之间来回切换,我们只需关注 CPU 的总时间即可。
一行中有 11 列,对应着不同的细分时间,分别为:
- user (1) 在用户态中花费的时间
- nice (2) 低优先级下在用户态中花费的时间
- system (3) 在内核态中花费的时间
- idle (4) 空闲时间
- iowait (5) 等待 I/O 完成的时间
- irq (6) 中断时间
- softirq (7) 软中断时间
- steal (8) 虚拟环境下在其他系统中花费的时间
- guest (9) 在虚拟化 CPU 上花费的时间
- guest_nice (10) 低优先级的 guest 时间
CPU 时间的单位为 USER_HZ,表示每秒钟时钟中断的次数,计算 CPU 总时间只需要将 每一行的数字 相加即可。
/proc/pid/stat
/proc/pid/stat
是有关进程的状态信息,使用 ps
命令时获取的就是这里的信息。运行 cat /proc/1/stat
命令的结果如下所示:
|
|
可以看到同样包含了非常多的信息,这里我们只需要关注这 4 个数字:
- utime (14) 进程在用户态中的时间
- stime (15) 进程在内核态中的时间
- cutime (16) 进程在用户态中等待子进程的时间
- cstime (17) 进程在内核态中等待子进程的时间
时间单位同样是 USER_HZ,计算进程占用 CPU 的时间秩序将这 4 个数值相加即可。
小结
简单介绍了如何通过 /proc/stat
与 /proc/pid/stat
计算进程的 CPU 使用率,我们取一定时间(例如 1 秒)内 CPU 总时间的差值与进程 CPU 时间的差值,将进程 CPU 时间差值除以 CPU 总时间差值再乘以 100% 即可得到某一进程短时间内的使用率。