最稳低开销的cpu占用率计算:windows用getsystemtimes(需注意权限、两次调用间隔≥100ms、filetime转微秒),linux读/proc/stat首行并按字段语义解析,跨平台避免std::chrono直接减系统时间戳,采样间隔宜200–500ms。
Windows 上用 GetSystemTimes 算 CPU 占用率,别碰 Performance Counter
Windows 下最稳、最低开销的方式是调用 GetSystemTimes,它返回内核态、用户态和空闲时间的 64 位累计 tick 数。自己差分再除以总时间就能算出占用率。很多人一上来就查 Performance Counter(比如 "\Processor(_Total)\% Processor Time"),结果发现初始化慢、权限要求高、多线程下容易卡住——它本质是 COM 接口封装,不适合高频采样。
- 必须每轮都调用两次:一次取旧值,间隔几百毫秒后再取新值,否则差分为 0
- 两次调用之间不能小于 100ms,否则精度崩(系统只在特定中断点更新这些计数器)
-
GetSystemTimes要求进程有SE_INCREASE_QUOTA_NAME权限,但普通 GUI 进程默认就有,服务进程可能需显式提权 - 返回的
FILETIME是 100ns 单位,要转成毫秒得除以 10000;总时间 = 用户 + 内核 − 空闲
Linux 下读 /proc/stat 的第一行,别 parse 全部字段
Linux 没有统一 syscall 提供 CPU 占用率,/proc/stat 是唯一可靠来源。关键只看第一行 cpu 开头那条(含所有 CPU 总和),后面每行 cpu0、cpu1 是单核数据,除非你真要监控核级负载。
- 该行字段顺序固定:
user nice system idle iowait irq softirq steal guest guest_nice,但内核版本不同字段数可能变(如 2.6.33+ 加了guest),所以务必按空格 split 后取前 8–10 个数字,别硬写索引 - 计算时只用
user + nice + system + irq + softirq当“忙时间”,idle + iowait当“空闲时间”;steal和guest属于虚拟化开销,一般不计入主机 CPU 占用 - 读
/proc/stat是纯文本 I/O,频繁调用(如每 100ms)会触发 page cache 压力,建议用mmap或至少read配合固定 buffer 复用
跨平台封装时,避免用 std::chrono 直接减 FILETIME 或 timespec
Windows 的 FILETIME 和 Linux 的 timespec 都是纳秒/100ns 级时间戳,但 std::chrono::steady_clock::now() 在不同平台底层实现不同(Windows 是 QPC,Linux 是 clock_gettime(CLOCK_MONOTONIC)),直接拿它们跟系统时间戳做减法会出错。