我想将 CPU 总利用率作为计数器进行监控。我希望它作为计数器的原因是样本之间的数据不会丢失(并且我可以让绘图端计算速率)。
我最初的方法是使用/proc/uptime
公式(uptime-(idle_time/num_core))*100
。这通常在大量服务器上似乎是准确的(大约 98% 的时间),但有时我似乎得到了错误的结果。例如,以下内容似乎表明存在负 CPU 使用率,这实际上没有意义:
[root@ny-lb05 ~]# echo -e "scale=10\n ($(cut -f1 -d' ' /proc/uptime)-($(cut -f2 -d' ' /proc/uptime)/16))*100" | bc
5646895.3750000000
[root@ny-lb05 ~]# echo -e "scale=10\n ($(cut -f1 -d' ' /proc/uptime)-($(cut -f2 -d' ' /proc/uptime)/16))*100" | bc
5646891.5625000000
在此服务器上我正在运行:
Linux ny-lb05.ds.stackexchange.com 2.6.32-431.11.2.el6.x86_64 #1 SMP Tue Mar 25 19:59:55 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
有人发现这种计算方法有错误吗?有没有更好的方法来获取 CPU 利用率作为计数器?
更新:
所以我追求的是作为单调递增计数器的总使用时间。我希望总利用率永远不应该减少。但以下情况似乎就是这种情况:
[root@ny-lb05 ~]# read uptime idle </proc/uptime; echo -e "scale=1000\n ($uptime*16-($idle))" | bc 903874.23 [root@ny-lb05 ~]# read uptime idle </proc/uptime; echo -e "scale=1000\n ($uptime*16-($idle))" | bc 903870.29
另外,根据 /proc/cpuinfo,cores=siblings 所以我相信 HT 没有启用。
更新2:
太长了; /proc/uptime 有 bug,请使用 /proc/stat 代替。
答案1
(正常运行时间-(idle_time/num_core))
可以了解系统忙碌了多长时间(以秒为单位)。将其乘以 100 就是厘秒——这是你的意图吗?
IMO 考虑总共有多少处理器可用秒,并从中减去空闲时间会更有意义:
uptime * num_core - idle_time = total active processor seconds
利用率指标可能是:
active seconds / (uptime * num_core)
例如,如果系统在 4 个核心上运行了 10 秒,空闲时间为 5 秒:
(10 * 4 - 5) / (10 * 4) = 0.875
利用率87.5%。
或者:
(10 - 5 / 4) / 10 = 0.875
同样的事情,节省了一个操作。
有没有更好的方法来获取 CPU 利用率作为计数器?
我在系统诊断 C++ 库中通过解析 的第一行来完成此操作/proc/stat
,这是所有内核的总和。前三个字段是用户时间、低优先级(也称为良好)时间和系统时间。这些的总和就是活动时间量(注意这里的单位不是秒,见/proc/stat
下文man proc
)。
如果您轮询超过 5 秒,假设 USER_HZ 为 100,其中total_a
是第一个样本 (user + Nice + sys),total_b
是第二个样本:
(total_b - total_a) / 5 / 100 / num_cores = usage ratio
如果将其乘以 100,您将得到一个百分比,表示 5 秒间隔内的平均值。
逻辑如下:
total_b - total_a
= 样本之间的活动时间除以样本的持续时间,即 5 秒。
除以每秒测量单位 (USER_HZ)
除以核心数
USER_HZ 几乎肯定是 100。要检查:
#include <stdio.h>
#include <unistd.h>
int main (void) {
printf (
"%ld\n",
sysconf(_SC_CLK_TCK)
);
return 0;
}
编译:gcc whatever.c
,运行./a.out
.
使用 shell 工具很难获得准确的持续时间,因此您可以增加总活动时间的测量值(我认为这是您的意图)或使用相当长的间隔,例如 30 秒以上。
答案2
您的问题可能是因为您正在/proc/cputime
从两个单独的进程中读取数据。每次之间的空闲时间会略有增加cat
,因此第二次读数可能会较低。我建议改为这样做:
read uptime idle </proc/cputime
echo -e "scale=10\n ($uptime-($idle/16))*100" | bc
另外,如果您希望结果是总利用率百分比,那么您应该再次除以正常运行时间:
read uptime idle </proc/cputime
echo -e "scale=10\n ($uptime-($idle/16))/$uptime*100" | bc