我有一位开发人员抱怨报告的 CPU 使用率/proc/stat
不一致。
我的理解是/proc/stat
计算滴答数,从内核 2.6 开始,滴答数已固定为 100/s
现在我对CPU1进行了观察,/proc/stat
它可能在一秒钟内计数超过100个滴答声,这应该是不可能的。
该脚本显示了我如何进行计算
cat /proc/uptime
b=`awk /cpu1/'{print $2+$3+$4+$5+$6+$7+$8+$9+$10+$11}' /proc/stat`
sleep 1
a=`awk /cpu1/'{print $2+$3+$4+$5+$6+$7+$8+$9+$10+$11}' /proc/stat`
cat /proc/uptime
expr $a - $b
输出示例
32.80 19.06
33.86 19.51
CPU1 jiffies/s 137
我对 中的字段进行求和/proc/stat
,稍等一下,然后再做一次。然后我有时会得到大约 140 的总和差。它相当稳定,可能会上下一些计数。
对于内核,CONFIG_HZ 为 100。如果我用 250 或 1000 进行编译,变化会变小,但它仍然存在。
似乎用户空间和空闲字段占据了大部分 jiffies。在一个示例中,我计算了 102 个用户空间 jiffies,这可以通过睡眠额外花费 20 毫秒来解释。因此用户空间一直占用。但随后还有 33 个空闲滴答声,这些滴答声是在已满预订的 CPU 上执行的。
我有一个双核 ARMv7 处理器,运行Linux kernel 4.14.34
RT 抢占补丁。与此同时,我正在运行一个实时控制应用程序。
我的问题是/proc/stat
数字不一致。但要理解这一点,我非常想理解为什么/proc/stat
可以数到100以上。
编辑:在脚本中添加了 cat /proc/uptime
答案1
您使用的脚本是主要问题。就延迟而言,上下文切换的成本非常高。
sleep 1
让你的脚本进入睡眠状态。当计时器完成时,进程将再次变得可运行,也可能被重新分配到 CPU 的另一个核心(迁移)。所以基本上你并没有/proc/stat
精确地每 1000 毫秒轮询一次,正如你在帖子中所说的那样。
顺便说一句,这并不是评估 RT 内核的好方法。
我真的邀请您使用sysjitter
Solarflare 的例子系统抖动 openonload这将为您提供更好的关于内核运行情况的指标。
主要概念是,将一个无限循环固定到一个核心(每个核心 1 个运行线程),该循环汇集核心的时间戳计数器 (TSC) 寄存器,并比较以下两个值以查看每次内核运行时可能发生的差异抢占正在运行的进程(假设为100hz)。
这样,您将对服务器的系统抖动有更好的了解,并决定对其进行更多调整。
此外,如果您的用例需要此类改进,您还应该考虑 cpu 隔离、为您的应用程序提供专用核心以及动态滴答内核配置。
编辑:我建议您只使用awk
像这样的小脚本来满足您的所有需求:
#!/usr/bin/awk
BEGIN {
sum1=0;
sum2=0;
result=0;
file="/proc/stat";
while (( getline < file ) > 0 ) {
if ($1=="cpu1"){ sum1=$2+$3+$4+$5+$6+$7+$8+$9+$10+$11 };
}
close(file) ;
print "firt time " sum1;
system("sleep 10");
while (( getline < file ) > 0 ) {
if ($1=="cpu1") { sum2=$2+$3+$4+$5+$6+$7+$8+$9+$10+$11 }
}
close (file)
print "secont time " sum2;
result=sum2-sum1;
print "sum is " result/10;
}
该采样时间超过 10 秒,并将结果除以 10 以获得 1 秒切片的平均时间。