/proc/stat CPU tick计数异常排查(Docker绑定CPU核心场景)
分析与解答
1. NOHZ(自适应时钟)是核心诱因
当内核启用CONFIG_NO_HZ_FULL(针对无干扰CPU核心的完全自适应时钟)或CONFIG_NO_HZ_IDLE时,绑定了容器的核心1可能被标记为无HZ核心:这类核心在空闲时会停止时钟tick计数,仅在任务调度、系统调用或中断触发时才更新tick统计。
即使核心1存在25%的线程负载,仍会出现tick计数缺失,原因在于:
- 容器内的线程属于用户态任务,若该线程在核心1上持续运行,NOHZ模式下内核不会按固定HZ(100次/秒)生成tick,仅在任务切换、系统调用或中断发生时才刷新累计tick值。
- 采样周期为1秒,若采样窗口内核心1上的用户态线程未触发任何需要更新tick的事件,
/proc/stat的累计tick值就无法完整记录这段时间的CPU使用,导致计算出的差值远低于100。
2. cgroups v2的CPU统计逻辑差异
启用cgroups v2后,内核对绑定到cgroup的核心的统计方式发生了变化:
/proc/stat是全局CPU统计,而cgroup的CPU使用会通过/sys/fs/cgroup/cpu.stat单独记录。当容器绑定核心后,/proc/stat对核心1的统计可能未正确关联cgroup内的任务tick,导致统计遗漏。- 而
/proc/[进程PID]/stat直接记录进程/线程的累计tick,不受全局核心统计的cgroup关联问题影响,因此能准确反映线程负载。
3. 其他可能原因的排除
- CPU governor:已切换performance/ondemand模式无影响,排除调频导致的tick计数偏差。
- IRQ负载:irq列为空且网络IRQ在核心0,排除IRQ未被统计的问题。
- 采样精度:多场景复现且已排除脚本精度问题,可排除偶然误差。
验证建议
- 临时禁用核心1的NOHZ:执行
echo 0 > /sys/devices/system/cpu/cpu1/nohz_full(部分内核版本支持),再观察/proc/stat的tick差值是否恢复至100左右。 - 对比cgroup统计:查看容器对应的
/sys/fs/cgroup/[容器cgroup路径]/cpu.stat中的usage_usec字段,计算每秒差值,确认是否与线程负载匹配。
内容的提问来源于stack exchange,提问作者computer007
相关产品推荐
相关产品推荐

