问题与 Linux cgroups CPU 核算有关。
我在容器级别注意到了这一点,但它一直持续到顶层。例如:
# cat /sys/fs/cgroup/cpu/cpuacct.stat /sys/fs/cgroup/cpu/cpuacct.usage
user 34618
system 18038
743932863030
前者的单位是百分之一秒,后者的单位是纳秒,即 346.18、180.38 和 743.932863030
我的问题是:为什么前两个与后者不相等?
您可能会想“啊,它们从不同的起源开始”,所以几分钟后这里是相同的指标:
# cat /sys/fs/cgroup/cpu/cpuacct.stat /sys/fs/cgroup/cpu/cpuacct.usage
user 40028
system 22098
818501029494
增量分别为 54.1、40.6 和 74.57。
答案1
我不是内核开发人员,但是,通过研究内核源代码,我发现 cpuacct.usage(通过cgroup_account_cputime)和 cpuacct.stat(通过更新cgroup_account_cputime_field似乎是由不同的内核组件计算的。
据我所知,cpu.stat 的输出似乎很大程度上取决于内核配置,特别是配置_VIRT_CPU_ACCOUNTING_GEN,配置_VIRT_CPU_ACCOUNTING_NATIVE和配置_VIRT_CPU_ACCOUNTING。从他们的描述来看,他们似乎更精确。相关文件是内核/sched/cputime.c其中定时更新似乎是由一些内核事件(irqs 等)引起的。
cpuacct.usage 的输出似乎是调度程序在任务之间切换时计算的。例如更新当前,它调用 cgroup_account_cputime 来调用入队实体和 dequeue_entity 似乎可以安排任务。这似乎不受配置的影响。
答案2
cpuacct.stat
包含 cgroup 中进程的累计 CPU 使用率,以 1/100 秒的刻数表示,也称为“用户 jiffies”(USER_HZ
)。它可能不如以纳秒为单位的 CPU 时间精确。
您可以USER_HZ
从 shell 获取(通常100
)
$ getconf CLK_TCK
100
这应该映射到每秒的调度程序刻数,除非你处于实时或无滴答内核。
cpuacct.usage
给出以纳秒为单位的总体 CPU 时间,其测量精度与内核报告的使用时间一样精确。
cpuacct.usage_all
或者cpuacct.usage_percpu
将再次以纳秒为单位报告每个 CPU 核心(线程)的使用情况。
请注意,cpuacct
子系统最初是作为 cgroups 功能的演示而编写. 它并非用于精确报道。