CPU使用率和负载

CPU使用率和负载

本篇未完结

在刚工作时我对 CPU使用率这个词没有多少理解,只是知道代表当前CPU是否繁忙,是否有在运行程序而已,并没有过多的思考。

导致一些问题很模糊,如

  1. 使用率100%了会发生什么?
  2. 使用率始终上不去怎么办
  3. 多核心CPU的个别核心忙会不会影响整体使用率
  4. 温度是否会影响使用率
  5. 使用率高是否应用程序响应就会变慢
  6. 长期100%机器是否会炸?系统是否会崩?
  7. 是什么原因导致使用率忽高忽低的?
  8. 是怎么计算出这个值来的?
  9. CPU使用率和CPU负载有什么区别的联系?

尴尬的小故事

第一份运维工作刚入职的时候,下班时要发一封巡检报告邮件给客户和项目组领导,里面就包括今天top10的主机的CPU使用率和负载的指标,还有一些其它的主机和业务指标。
前同事交接给我时说他的做法就是下班前随机抽几台机器执行 top 看一眼,填几个数就完事了。

我一想,这不糊弄人嘛,我可是社会主义好青年,以后我不能这样做,得实事求是。

开始几天我当然还是按照他的方法写巡检报告,下班前需要1个半小时才能做完,主要是还有一些其它指标和多个SQL的原因,他做也差不多需要这么长时间。

于是我就想着如何提高效率,发现当时有部署一个 nagios 的监控系统,上面有很多监控指标和数据。我想既然有现成的数据,就不用再去这些机器上执行命令查询了呗。

于是写了一个shell脚本,每5分钟拉取一次 nagios 页面上的数据, 然后过滤需要的指标数据到一个文件,
然后在下班前执行数据汇总脚本,提取当天数据的top10, 然后写报告时复制过来就行。

这样可是在全天全量数据上取的top10,相比前同事只是下班前随机瞄一眼的方式肯定是更准确。

但当时这个监控系统上居然没有监控CPU使用率这一项,只有一个CPU负载的数据。
这怎么办呢?
最好是给 nagios 加上这个指标,但当时我还不会配置,前同事也不会配置,说是使用的默认监控模板。

于是我做了一个错误的决定。
我在用 top 命令观察了一会几台主机和CPU使用率和负载的关系后,得出了 CPU负载除以2就和CPU使用率差不多的简单结论。

于是我的自动化脚本就按这个条件输出主机的CPU使用率。

在第三天发送巡检报告后,项目经理回邮件质问我为什么这几天的CPU使用率相比之前高出了那么多。
我当然不能说是因为前同事糊弄啊,他还在职呢;(这类项目邮件都是默认抄送全部项目成员的)。

于是我就解释之前是下班前全量统计并取top10的,但这个时间不是业务高峰期,高峰期在早上10点,新统计办法覆盖到了全天,所以数据更准确了。

项目接着邮件问那你这个CPU使用率的数据是怎么来的?

当时我居然写了很长一段看起来比较专业的内容来说明这个值是根据CPU负载计算出来的,并写出了公式和依据(找了几台机器top截图)。

项目经理然后回复说,小陈同学很专业啊,有创新精神,提高了事务效率等等一些话,号召大家多学习等等。

后来我觉得他应该不是在阴阳我,他应该也不懂,整个项目组几名运维和开发居然也都不懂。

后来几天我总觉得这个计算方法不对,因为还是有几台机器不是2倍的。
于是网上找了很多资料补习后才算搞清楚。

操作系统基础

分时操作系统

CPU的一个核心同一时间只能处理一个任务。
但是有些任务需要运行很长时间,但却不是一直在使用CPU。比如一个秒级别时钟显式程序,只需要在整数秒的时候运行并刷新一下屏幕就可以了,实际这一秒内真实CPU占用可能不到1毫秒,那么就白白浪费了其它999毫秒。

于是出现了多任务分时操作系统
把这1秒分成N份,多个程序来回切换,各自只占用这1秒内的一部分时间,就达到了这1秒内同时在运行很多程序的效果。

详细说就是CPU如果是 2.40GHz 的,则代表每秒能执行 2.4G 次任务;
但是一般按10ms为单位划分成了多个时间片;也就是说这1秒内最多运行100个时间片,每个时间片内最多24MHz的任务数,每个时间片归属于1个进程或线程去运行。

问题是: 难道1秒内最多只能运行100个程序?
否,因为如果某个程序在这个10ms时间内提前退出了,那么这部分未使用的时间就被让出来了。
只有这个100个程序都是满负荷运行的情况,我们才可以说这1秒最多只有100个程序在使用;
但这只是理论,实际上操作系统的某些系统级别高优先级程序也需要运行,只是占用的时间片短而已。

有个问题就出现了,我这个时钟程序怎么保持精度呢?
例如现在的时间是 1:58, 你问朋友现在几点了,他告诉你现在是1点,你可能会想当然的认为现在才1点过几分钟。

这就要看需不需要时间精度了。

首先,如果是不太需要很精确的时钟程序,那么在这1秒的头部或者尾部运行是没有太大关系的。
比如墙上的钟表,我们一般只关心到分钟,最多精确到秒。
没有人会去关注它是不是在毫秒级别和北京时间的原子钟同步的。
你在这1秒的前几毫秒或后几毫秒运行都无所谓。

目前主流操作系统都是分时操作系统。

实时操作系统

如果确实需要固定的毫秒级别,甚至微秒级别呢?
比如我这个程序就需要在 下午1点20分53秒20毫秒30微秒的时间执行,或者是本次执行后的固定10毫秒后执行,差1微秒都不行这种怎么办呢?

当然就是靠实时操作系统了。

实时操作系统的调度算法和分时的调度算法主要差异在,实时调度会提前计算好这个程序需要在哪个时间点上执行。
如果新任务的插队不会耽误原有任务的准时执行,那么可以插队;
如果插队的任务所需要的时间太长,会干扰原任务,就不可以插队,需要排队运行。

这就导致实时调度系统一般有效利用率不会很高。

一般场景就是军用、卫星、工业等等时间精度要求非常高的场合。

CPU 性能

对于我们这类普通用户而言,我们对于一个 CPU 的要求,无外乎几个;

  1. 它运行程序快不快
  2. 运行多个程序会不会卡
  3. 运行久了会不会变慢

于是我们通常关系3个指标

  1. CPU使用率
    相同的平台运行同一个软件,一个CPU使用率100%,一个只有50%;
    我们通常会认为第一个 程序没有问题,CPU到达瓶颈了;
    第二个则是 CPU 没问题,程序需要优化;

  2. CPU 负载
    如果负载为 0.5, 表示这1秒内只有半秒在运行程序,所以即便卡,那也不是CPU问题
    如果负载为 1,表示这1秒内已经满

CPU 使用率

很多工具都可以统计使用率, 如 top vmstat sar 等等, 它们是如何取到的值呢?
都是从 /proc/stat 这个系统接口文件获取的值

文件解析(开头几行)

1
2
3
4
5
6
[root@wcn7 ~]# cat /proc/stat
cpu  1310820 44 844639 90656257 43593 479534 246949 0 0 0
cpu0 331387 3 211082 22653168 11345 121616 62364 0 0 0
cpu1 323568 7 210623 22668591 8091 122141 63697 0 0 0
cpu2 327764 16 211294 22668241 11326 117840 60776 0 0 0
cpu3 328099 16 211638 22666256 12829 117935 60111 0 0 0

第一行是汇总数据, 下面几行是每个CPU核心单独的数据
以第一行后面的数据为例,数据的单位是1个时间片

分别解释
user 用户态占用, 即这个时间片是被用户态的应用程序给占用了,一般来说等同与业务程序使用的资源
nice 低优先级进程的占用, 也是用户态的程序使用的, 但是没有使用默认的调度优先级
system 内核态占用,即一些系统调用后内核运行所占用的时间
idle 除IO等待时间以外的其它等待时间片
iowait IO等待时间,因为IO等待而造成CPU空闲的时间
irq 硬中断时间
softirq 软中断时间

CPU负载

从 /proc/loadavg 接口文件取值

1
2
[root@wcn7 ~]# cat /proc/loadavg
0.21 0.16 0.16 1/765 7058

本篇未完结

Licensed under CC BY-NC-SA 4.0
转载或引用本文时请遵守许可协议,知会作者并注明出处
不得用于商业用途!
最后更新于 2023-11-21 00:00 UTC