一、核心公式(工程上真正使用的)

进程 CPU 使用率必须是“两个时间点之间的差值”,公式如下:

CPU% = (Δ(utime + stime) / Δtotal_cpu_time) × NCPU × 100%

或更常见等价形式:

CPU% = Δproc_time / Δwall_time × 100%

取决于你用哪种参照系。

下面解释清楚。


二、utime / stime 是什么单位?

单位不是秒,而是:

clock ticks

转换成秒:

seconds = ticks / sysconf(_SC_CLK_TCK)

查看:

getconf CLK_TCK

通常:

100

表示:

1 tick = 10 ms

三、方法 1:最直观工程计算法(推荐)

步骤:

Step 1:读取进程 CPU 时间

cat /proc/<pid>/stat

第 14、15 字段:

utime stime

例如:

第一次:

utime = 1200
stime = 300
total = 1500

1 秒后:

utime = 1300
stime = 400
total = 1700

增量:

Δproc = 200 ticks

Step 2:换算为秒

如果 CLK_TCK = 100:

200 ticks = 2 seconds CPU time

Step 3:除以实际时间

假设采样间隔 1 秒:

CPU% = 2 / 1 × 100% = 200%

表示:

使用了 2 个 CPU 核心满载


四、为什么可以超过 100%?

因为进程可以多线程并行:

1 核满载  = 100%
2 核满载  = 200%
8 核满载  = 800%

top 的显示就是这样。


五、方法 2:用 /proc/stat 作为基准(更精确)

读取:

cat /proc/stat

第一行:

cpu  user nice system idle iowait irq softirq steal ...

计算:

total_cpu_time = 所有字段之和

然后:

CPU% = Δproc_time / Δtotal_cpu_time × NCPU × 100%

这是 top 的实现方式。


六、完整 Python 示例(工程级)

import time

CLK_TCK = 100

def read_proc_time(pid):
    with open(f"/proc/{pid}/stat") as f:
        fields = f.read().split()
        utime = int(fields[13])
        stime = int(fields[14])
        return utime + stime

pid = 1234

t1 = read_proc_time(pid)
time.sleep(1)
t2 = read_proc_time(pid)

delta = t2 - t1

cpu_percent = delta / CLK_TCK * 100

print(cpu_percent, "%")

七、utime vs stime 的工程意义

它们回答不同问题:

字段 含义 判断什么问题
utime 用户态执行时间 算法 / 计算
stime 内核态执行时间 syscall / IO / kernel

八、工程诊断意义(非常重要)

情况 1:utime 高

utime >> stime

说明:

CPU 花在用户代码

原因:

  • 算法复杂
  • 死循环
  • 计算密集

情况 2:stime 高

stime >> utime

说明:

CPU 花在内核

原因:

  • write()
  • read()
  • 网络
  • 文件系统
  • 锁竞争

情况 3:CPU% 低,但进程卡

检查:

D state

说明:

在等 IO

不是 CPU 问题。


九、top 的 %CPU 本质就是这个公式

top 每隔一段时间:

读取 proc stat
计算差值
显示 %

不是瞬时值。


十、一张完整因果链图

进程运行

utime 增加

stime 增加

proc total time

两次采样求差

除以时间间隔

得到 CPU%


十一、一句话工程总结

进程 CPU 使用率,本质是“单位时间内消耗的 CPU 时间”,
utime + stime 提供了这个时间,而 CPU% 是它的变化速率。


在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐