admin 管理员组

文章数量: 1184232

1. CPU 负载与 CPU 使用率

尽管 CPU 负载和 CPU 使用率听起来很相似,但它们是不可互换的。

  • CPU 负载定义为在单个时间点使用或等待使用一个内核的进程数。
    平均负载(load average)是指某段时间内占用cpu时间的进程和等待cpu时间的进程数,这里等待cpu时间的进程是指等待被唤醒的进程,不包括处于wait状态进程。
  • CPU 使用率是 CPU 处理非空闲任务所花费的时间百分比。CPU 使用率只能在指定的时间间隔内测量。我们可以通过将空闲时间的百分比从 100 中减去来确定 CPU 使用率。
    cpu使用率反映的是当前cpu的繁忙程度,忽高忽低的原因在于占用cpu处理时间的进程可能处于io等待状态但却还未释放进入wait。

假设我们有一个单核系统,我们的 CPU 平均负载始终低于 0.6 。这表明每个需要使用 CPU 的进程都可以立即使用它,而无需等待。如果 CPU 平均负载大于 1 ,则表示有进程需要使用 CPU,但由于 CPU 不可用,目前无法使用。

但是,多处理器系统中高于 1 的平均负载不会成为问题,因为有更多内核可用。

uptime 命令为我们提供了以 1 5 15 分钟为间隔的平均负载视图:

uos@uos-PC:~$ uptime10:01:13 up 10 days, 19:42,  2 users,  load average: 3.01, 3.04, 3.01

uptime 命令用于显示系统运行时间及负载。
uptime 命令可以打印出系统总共运行了多长时间和系统的平均负载。 uptime 命令显示的信息显示依次为:现在时间、系统已经运行了多长时间、目前有多少登陆用户、系统在过去的 1 分钟、 5 分钟和 15 分钟内的平均负载。

命令语法
uptime [ options ]
-p #以好看的格式显示正常运行时间
-s #自系统启动来的时间
-h #打印帮助信息
-V #打印版本信息。

如果不知道系统的核心数,就无法解释平均负载:

uos@uos-PC:~$ cat /proc/cpuinfo |grep core
core                    :0
core                    :1
core                    :2
core                    :3

但是在X86系统上是

uos@uos-PC:~$  cat /proc/cpuinfo |grep core
core id:0
cpu cores       :8
core id:1
cpu cores       :8
core id:2
cpu cores       :8
core id:3
cpu cores       :8
core id:4
cpu cores       :8
core id:5
cpu cores       :8
core id:6
cpu cores       :8
core id:7
cpu cores       :8

2. 计算CPU使用率

2.1 使用vmstat获取 CPU 使用率

2.1.1 vmstat工具

vmstat Virtual Meomory Statistics (虚拟内存统计)的缩写, 是实时系统监控工具。该命令通过使用 knlist 子程序和 /dev/kmen 伪设备驱动器访问这些数据,输出信息直接打印在屏幕。 vmstat 反馈的与CPU相关的信息包括:
(1)多少任务在运行
(2)CPU使用的情况
(3)CPU收到多少中断
(4)发生多少上下文切换

2.1.2 参数用法
vmstat[-a][-n][-S unit][delay [ count]]vmstat[-s][-n][-S unit]vmstat[-m][-n][delay [ count]]vmstat[-d][-n][delay [ count]]vmstat[-p disk partition][-n][delay [ count]]vmstat[-f]vmstat[-V]
-a:显示活跃和非活跃内存
-f:显示从系统启动至今的fork数量 。
-m:显示slabinfo
-n:只在开始时显示一次各字段名称。
-s:显示内存相关统计信息及多种系统活动数量。
delay:刷新时间间隔。如果不指定,只显示一条结果。
count:刷新次数。如果不指定刷新次数,但指定了刷新时间间隔,这时刷新次数为无穷。
-d:显示磁盘相关统计信息。
-p:显示指定磁盘分区统计信息
-S:使用指定单位显示。参数有 k 、K 、m 、M ,分别代表1000、1024、1000000、1048576字节(byte)。默认单位为K(1024 bytes)
-V:显示vmstat版本信息。
2.1.3 使用方法:

一般 vmstat 工具的使用是通过两个数字参数来完成的,第一个参数是采样的时间间隔数,单位是秒,第二个参数是采样的次数,如:

root@uos-PC:/home/uos# vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 000367782448802166688000858109900000367785648802166688000213062814109900000367713648802166688000095218691198000003677136488021666880001270011140010000000367638448802166688000019794483119800
  • us –运行非内核代码所花费的时间
  • sy -运行内核代码所花费的时间
  • id –空闲时间
  • wa –等待 I/O 所花费的时间
  • st -从虚拟机中窃取时间
  • id列是我们感兴趣的。延迟一秒,我们使用 vmstat 计算CPU使用率:
    root@uos-PC:/home/uos# echo "CPU Usage: "$[100-$(vmstat 1 2|tail -1|awk '{print $15}')]"%"
    CPU Usage: 0%
    root@uos-PC:/home/uos# echo "CPU Usage: "$[100-$(vmstat 1 2|tail -1|awk '{print $15}')]"%"
    CPU Usage: 1%
    root@uos-PC:/home/uos# echo "CPU Usage: "$[100-$(vmstat 1 2|tail -1|awk '{print $15}')]"%"
    CPU Usage: 2%
    root@uos-PC:/home/uos# echo "CPU Usage: "$[100-$(vmstat 1 2|tail -1|awk '{print $15}')]"%"
    CPU Usage: 1%
    root@uos-PC:/home/uos# echo "CPU Usage: "$[100-$(vmstat 1 2|tail -1|awk '{print $15}')]"%"
    CPU Usage: 0%
    

procs
r 列表示运行和等待cpu时间片的进程数,如果长期大于1,说明cpu不足,需要增加cpu。当这个值超过了CPU数目,就会出现CPU瓶颈了。
b 列表示在等待资源的进程数,比如正在等待I/O、或者内存交换等。
cpu 表示cpu的使用状态
us 列显示了用户方式下所花费 CPU 时间的百分比。us的值比较高时,说明用户进程消耗的cpu时间多,但是如果长期大于50%,需要考虑优化用户的程序。
sy 列显示了内核进程所花费的cpu时间的百分比。这里us + sy的参考值为80%,如果us+sy 大于 80%说明可能存在CPU不足。系统CPU时间,如果太高,表示系统调用时间长,例如是IO操作频繁。
wa 列显示了IO等待所占用的CPU时间的百分比。这里wa的参考值为30%,如果wa超过30%,说明IO等待严重,这可能是磁盘大量随机访问造成的,也可能磁盘或者磁盘访问控制器的带宽瓶颈造成的(主要是块操作)。
id 列显示了cpu处在空闲状态的时间百分比。空闲 CPU时间,一般来说,id + us + sy = 100,一般我认为id是空闲CPU使用率,us是用户CPU使用率,sy是系统CPU使用率。
system 显示采集间隔内发生的中断数
in 列表示在某一时间间隔中观测到的每秒设备中断数。
cs 列表示每秒产生的上下文切换次数,如当 cs 比磁盘 I/O 和网络信息包速率高得多,都应进行进一步调查。每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。
memory
swpd 切换到内存交换区的内存数量(k表示)。如果swpd的值不为0,或者比较大,比如超过了100m,只要si、so的值长期为0,系统性能还是正常。否则,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。
free 当前的空闲页面列表中内存数量(k表示)
buff 作为buffer cache的内存数量,一般对块设备的读写才需要缓冲。
cache : 作为page cache的内存数量,一般作为文件系统的cache,如果cache较大,说明用到cache的文件较多,如果此时IO中bi比较小,说明文件系统效率比较好。
swap
si 由内存进入内存交换区数量。
so 由内存交换区进入内存数量。
IO
bi 从块设备读入数据的总量(读磁盘)(每秒kb)。
bo 块设备写入数据的总量(写磁盘)(每秒kb)
这里我们设置的bi+bo参考值为1000,如果超过1000,而且wa值较大应该考虑均衡磁盘负载,可以结合iostat输出来分析。

没有提供任何参数的 vmstat 命令将给出自引导以来的 CPU 时间。这不会提供准确的 CPU 使用百分比。因此,参数只能是 1 2 ,我们采用一秒钟后计算的指标:

root@uos-PC:/home/uos# vmstat 1 2
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 000369336048802167232000859109900000369336048802167232000079514930010000

2.2 使用/proc/stat获取 CPU 使用率

CPU 活动也可以从 /proc/stat 文件中提取。该文件包含自启动以来有关系统的各种指标:

root@uos-PC:/home/uos# cat /proc/stat
cpu  19480541611035720370133728593705188000
cpu0 4122514024308692487496121604782000
cpu1 469232532487129257673215610276000
cpu2 46375531246356926669381378069000
cpu3 60281536297565924025591780060000
intr 9649664450000000000000000000000000080200000000000569000036060745779550970851651209779612448000000000000943106500001022969316200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ctxt 1880902718
btime 1657693134
processes 1265552
procs_running 1
procs_blocked 0
softirq 6839838381326085391769931197796540012832270822560185567404

第一行 cpu 是系统所有核心指标的聚合。在具有 4 个内核的系统上,将有 4条cpu线—— cpu0 cpu1 cpu2 cpu3 cpu 行中的列表示处理不同任务所花费的时间:

  • user – 在用户模式下花费的时间
  • nice – 在用户模式下处理 nice 进程所花费的时间
  • system – 执行内核代码所花费的时间
  • idle - 空闲时间
  • iowait – 等待 I/O 所花费的时间
  • irq - 服务中断所花费的时间
  • softirq – 服务软件中断所花费的时间
  • steal —从虚拟机中窃取的时间
  • guest - 为来宾操作系统运行虚拟 CPU 所花费的时间
  • guest_nice – 为“不错的”客户操作系统运行虚拟 CPU 所花费的时间

使用这些指标来计算平均空闲百分比。随后,我们将使用计算值来计算 CPU 使用率。需要注意的是,较旧的 Linux 发行版不计算窃取、来宾或来宾_nice指标。如果我们使用的是旧系统,我们会在计算中忽略这些指标:

平均空闲时间 (%)=(idle * 100) / (user + nice + system + idle + iowait + irq + softirq +steal + guest + guest_nice)
  1. 单核系统
    发单核系统,因此 cpu 行将与 cpu1 相同。因此, tail -1 的使用是 只检索其中一行。
    root@uos-PC:/home/uos# cat /proc/stat |grep cpu |tail -1|awk '{print ($5*100)/($2+$3+$4+$5+$6+$7+$8+$9+$10)}'|awk '{print "CPU Usage: " 100-$1}'
    CPU Usage: 0.967
  2. 多处理器系统
    在多处理器系统上使用 cpu 行,因为它是所有内核上的指标的集合。
    root@uos-PC:/home/uos# cat /proc/stat |grep cpu|awk '{print ($5*100)/($2+$3+$4+$5+$6+$7+$8+$9+$10)}'|awk '{print "CPU Usage: " 100-$1}'
    CPU Usage: 0.8027
    CPU Usage: 0.7101
    CPU Usage: 0.7716
    CPU Usage: 0.7619
    CPU Usage: 0.967

2.3 使用top获取 CPU 使用率

通常, top 命令通常用于显示系统上的活动进程以及这些进程消耗了多少资源。不过,我们可以使用这个命令来测量 CPU 的状态:

top - 10:31:01 up 10 days, 20:12,  2 users,  load average: 3.00, 3.02, 3.00
Tasks: 216 total,   1 running, 215 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  1.6 sy,  0.0 ni, 98.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :7988.9 total,   3589.5 free,   2278.2 used,   2121.1 buff/cache
MiB Swap:  20480.0 total,  20480.0 free,      0.0 used.   4488.3 avail Mem

此外,需要注意的是, top 命令显示了单个内核的 CPU 百分比。在多处理器系统中,CPU 百分比可能超过 100% 。例如,如果 4 个核心为 75% top 命令将显示 CPU 为 300%

我们需要获取空闲时间的值,以便我们可以从 100 中减去它来获得使用情况:

root@uos-PC:/home/uos# top -bn2 | grep '%Cpu' | tail -1 | grep -P '(....|...) id,'|awk '{print "CPU Usage: " 100-$8 "%"}'
CPU Usage: 1.2%
root@uos-PC:/home/uos# top -bn2 | grep '%Cpu' | grep -P '(....|...) id,'|awk '{print "CPU Usage: " 100-$8 "%"}'
CPU Usage: 7.8%
CPU Usage: 0.8%
root@uos-PC:/home/uos# top -bn4 | grep '%Cpu' | grep -P '(....|...) id,'|awk '{print "CPU Usage: " 100-$8 "%"}'
CPU Usage: 1.6%
CPU Usage: 0.7%
CPU Usage: 1.1%
CPU Usage: 0.7%

-n 选项是 top 命令在结束前应该使用的迭代次数。我们避免使用第一个循环,因为我们检索的指标将是自启动以来的值。因此,我们进行了第二次迭代。

在多处理器系统中,我们必须将给定的 id 值除以内核数,然后从 100 中减去该值。例如,如果我们在四核系统上运行,并且 id 值为 304% ,我们将 CPU 使用率计算为:

CPU 使用率 % =100(304/4)
root@uos-PC:/home/uos# top -bn2 | grep '%Cpu' | tail -1 | grep -P '(....|...) id,'|awk '{print "CPU Usage: " 100-($8/4) "%"}'
CPU Usage: 75.225%

3. CPU负载的一个类比

判断系统负荷是否过重,必须理解 load average 的真正含义。下面,根据"Understanding Linux CPU Load"这篇文章解释这个问题。

首先,假设最简单的情况,你的电脑只有一个CPU,所有的运算都必须由这个CPU来完成。

那么,我们不妨把这个CPU想象成一座大桥,桥上只有一根车道,所有车辆都必须从这根车道上通过。(很显然,这座桥只能单向通行。)

  • 系统负荷为 0 ,意味着大桥上一辆车也没有。
  • 系统负荷为 0.5 ,意味着大桥一半的路段有车。
  • 系统负荷为 1.0 ,意味着大桥的所有路段都有车,也就是说大桥已经"满"了。但是必须注意的是,直到此时大桥还是能顺畅通行的。
  • 系统负荷为 1.7 ,意味着车辆太多了,大桥已经被占满了(1 00% ),后面等着上桥的车辆为桥面车辆的 70%
  • 以此类推,系统负荷 2.0 ,意味着等待上桥的车辆与桥面的车辆一样多;
  • 系统负荷 3.0 ,意味着等待上桥的车辆是桥面车辆的 2 倍。

总之,当系统负荷大于``1,后面的车辆就必须等待了;系统负荷越大,过桥就必须等得越久。

CPU的系统负荷,基本上等同于上面的类比。大桥的通行能力,就是CPU的最大工作量;桥梁上的车辆,就是一个个等待CPU处理的进程( process )。

如果CPU每分钟最多处理 100 个进程,那么:

  • 系统负荷 0.2 ,意味着CPU在这 1 分钟里只处理 20 个进程;
  • 系统负荷 1.0 ,意味着CPU在这 1 分钟里正好处理 100 个进程;
  • 系统负荷 1.7 ,意味着除了CPU正在处理的 100 个进程以外,还有 70 个进程正排队等着CPU处理。

为了电脑顺畅运行,系统负荷最好不要超过 1.0 ,这样就没有进程需要等待了,所有进程都能第一时间得到处理。很显然, 1.0 是一个关键值,超过这个值,系统就不在最佳状态了,你要动手干预了。

4. CPU负载-多处理器

上面,我们假设你的电脑只有1个CPU。如果你的电脑装了2个CPU,会发生什么情况呢?
2个CPU,意味着电脑的处理能力翻了一倍,能够同时处理的进程数量也翻了一倍。
还是用大桥来类比,两个CPU就意味着大桥有两根车道了,通车能力翻倍了。

所以,2个CPU表明系统负荷可以达到 2.0 ,此时每个CPU都达到 100% 的工作量。推广开来, n 个CPU的电脑,可接受的系统负荷最大为 n.0

5. CPU负载-多核处理器

芯片厂商往往在一个CPU内部,包含多个CPU核心,这被称为多核CPU。
在系统负荷方面,多核CPU与多CPU效果类似,所以考虑系统负荷的时候,必须考虑这台电脑有几个CPU、每个CPU有几个核心。然后,把系统负荷除以总的核心数,只要每个核心的负荷不超过 1.0 ,就表明电脑正常运行。
怎么知道电脑有多少个CPU核心呢?
cat /proc/cpuinfo 命令,可以查看CPU信息。
grep -c 'model name' /proc/cpuinfo 命令,直接返回CPU的总核心数。

root@uos-PC:/home/uos# grep -c 'model name' /proc/cpuinfo4

6. 系统负荷的经验法则

1.0是系统负荷的理想值吗?
不一定,系统管理员往往会留一点余地,当这个值达到 0.7 ,就应当引起注意了。经验法则是这样的:

  • 当系统负荷持续大于 0.7 ,你必须开始调查了,问题出在哪里,防止情况恶化。
  • 当系统负荷持续大于 1.0 ,你必须动手寻找解决办法,把这个值降下来。
  • 当系统负荷达到 5.0 ,就表明你的系统有很严重的问题,长时间没有响应,或者接近死机了。你不应该让系统达到这个值。

7. 最佳观察时长

最后一个问题, load average 一共返回三个平均值---- 1 分钟系统负荷、 5 分钟系统负荷, 15 分钟系统负荷,----应该参考哪个值?

  • 如果只有 1 分钟的系统负荷大于 1.0 ,其他两个时间段都小于 1.0 ,这表明只是暂时现象,问题不大。
  • 如果 15 分钟内,平均系统负荷大于 1.0 (调整CPU核心数之后),表明问题持续存在,不是暂时现象。

所以,你应该主要观察" 15 分钟系统负荷 ",将它作为电脑正常运行的指标。

refer to





本文标签: 使用率 系统负荷 编程