CPU性能优化学习笔记:平均负载

平均负载基本含义

系统变慢时使用top或uptime查看系统平均负载情况:

[root@localhost ~]# uptime
 16:34:18 up 0 min,  2 users,  load average: 0.08, 0.03, 0.01

uptime命令每列含义:

16:34:18            #系统当前时间

up 40 min          #系统运行时间

2 users              #正在登陆用户数

load average: 0.08, 0.03, 0.01          #过去1分钟负载,过去5分钟负载、过去15分钟负载

系统负载平均数是单位时间内,系统处于可运行或不可中断状态的进程的平均数,即平均活跃进程数,它与CPU使用率没有直接关系。

   可运行状态的进程是指正在使用CPU或正在等待CPU的进程,即使用ps命令查看到的处于R(Running/Runnable)状态的进程。

    不可中断状态的进程是正处于内核态关键流程中的进程,并且这些流程不可打断,如常见的等待硬件设备的I/O响应,即使用ps命令查看到的D(Uninterruptible Sleep,也称为Disk Sleep)状态的进程。     例如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在未得到磁盘响应前它不能被其他进程中断,此时进程就处于不可中断状态。如果进程被打断了,就容易出现磁盘数据与进程数据不一致问题。所以不可中断状态实际上是系统对进程和硬件设备的一种保护机制

所以平均负载就是平均活跃进程数,直观理解是单位时间内的活跃进程数,但它实际上是活跃进程数的指数衰减平均值(系统的一种更快速的计算方式,可以理解成活跃进程数的平均值)。

既然平均的是活跃进程数,那么最理想的是,每个CPU上都刚好运行一个进程,这样每个CPU都得到充分利用。比如当平均负载为2时,意味着什么?

  • 在2个CPU的系统上,意味着所有CPU都刚好被完全占用
  • 在4个CPU的系统上,意味着CPU有50%的空闲
  • 在1个CPU的系统上,意味着有1/2的进程竞争不到CPU

平均负载为多少时合理

平均负载最理想情况是等于CPU个数。所以在评判平均负载时,首先需要知道系统有多少个cpu

[root@localhost ~]# cat /proc/cpuinfo| grep "processor"| wc -l   #查看逻辑CPU
2

获取CPU的个数后,就可以判断出,当平均负载比CPU个数还要大时,系统已经出现过载。uptime给出平均负载3个值都应该查看,3个不同时间间隔的平均值,给我们提供了分析系统负载趋势的数据来源,让我们更全面、更立体的理解目前的负载状况。    例如,北京初秋的天气,如果只看中午温度,可能认为在炎热的夏天,但是结合早、中、晚3个时间的温度,基本可以了解这一天天气状态。

    同样对于CPU的三个负载时间段也如此。    例如,在单CPU系统上看到平均负载为1.73,0.60,7.98,此刻表示在过去1分钟内,系统又73%的超载,而在15分钟内有689%的超载,从整体趋势看,系统的负载在降低。解释如下:

  • 1分钟、5分钟、15分钟的三个值基本相同或者相差不大,说明系统负载很平稳
  • 1分钟的值远远小于15分钟的值,说明系统最近1分钟的负载在减少,但过去15分钟内负载很大
  • 1分钟的值远远大于15分钟的值,说明系统最近1分钟的负载在增加,这种增加可能只是临时的,也可能持续增加,所以需要持续观察。但1分钟的平均负载接近或超过了CPU的个数,就意味着系统正在发生过载的问题,此时就要分析调查什么问题导致,并想办法优化

在实际生产环境中平均负载高于CPU数量的70%,就应该分析排查负载高的问题了。一旦负载过高,就可能导致进程响应变慢,进而影响业务的正常功能。但70%并不是绝对的,最推荐的方法,还是把系统的平均负载监控起来,根据更多的历史数据,判断负载的变化趋势。当发现负载有明显升高趋势时,例如负载翻倍了,再去做分析和调查。

平均负载与CPU使用率

平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。所以,它不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。

    等待I/O就是某个进程读取磁盘,此时这个进程就处于不可中断睡眠状态,实际没有占用CPU,但算作平均负载。所以平均负载高不一定CPU使用率高,可能是IO瓶颈导致平均负载高。

CPU使用率是单位时间内CPU繁忙情况的统计,与平均负载不一定完全对应。例如:

  • CPU密集型进程,使用大量CPU会导致平均负载升高,此时两者一致;
  • I/O密集型进程,等待I/O也会导致平均负载升高,但CPU使用率不一定很高;
  • 大量等待CPU的进程调度也会导致平均负载升高,此时CPU使用率也会比较高。

平均负载案例分析

实验环境准备

OS:Centos7.9

机器配置:2核CPU,8GB内存

安装stress和sysstat包,并打开3个终端连接同一台服务器

[root@localhost ~]# yum -y install stress sysstat

stress:一款Linux系统压力测试工具,通常用于模拟系统上的负载,以测试系统在高负载条件下的性能或稳定性。这里用作异常进程模拟平均负载升高的场景。

sysstat:包含了常用的Linux性能工具,用来监控和分析系统的性能。本此实验会用到mpstat和pidstat命令。

    mpstat:一个常用的多核CPU性能分析工具,用来实时查看每个CPU的性能指标,以及所有CPU的平均指标。

    pidstat:一个常用的进程性能分析工具,用来实时查看进程的CPU、内存、I/O以及上下文切换等性能指标。

测试前查看平均负载情况:

[root@localhost ~]# uptime
 10:18:55 up 44 min,  2 users,  load average: 0.00, 0.04, 0.06

场景一:CPU密集型进程

首先,在第一个终端运行stress命令,模拟一个CPU使用率100%的场景:

#--cpu 1:在一个CPU核心上模拟负载
#--timeout 600:stress工具将在运行后的600秒(10分钟)之后自动停止
[root@localhost ~]# stress --cpu 1 --timeout 600
stress: info: [12348] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd

接着,在第二个终端运行uptime查看平均负载的变化情况:

#-d:高亮显示变化的区域
[root@localhost ~] watch -d uptime
Every 2.0s: uptime                                                                                   Wed Sep 27 10:27:06 2023

 10:27:06 up 52 min,  4 users,  load average: 0.99, 0.59, 0.28

最后,在第三个终端运行mpstat查看CPU使用率变化情况:

#-P ALL:显示每个CPU核心的详细信息,而不仅仅是汇总信息
#5:每隔5秒生成一次性能统计信息的报告
[root@localhost ~]# mpstat -P ALL 5
Linux 3.10.0-1160.el7.x86_64 (localhost.localdomain)    09/27/2023      _x86_64_        (2 CPU)

10:27:39 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
10:27:44 AM  all   50.05    0.00    0.10    0.00    0.00    0.00    0.00    0.00    0.00   49.85
10:27:44 AM    0    8.78    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   91.22
10:27:44 AM    1   91.40    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    8.40

结论:从第二终端看到,1分钟的平均负载会慢慢增加到1.00。从终端三中看到,只有一个CPU的使用率是100%,而且%iowait 是0。这说明,平均负载的升高是由于 CPU 使用率为100%引起的。

使用pidstat查看哪个进程导致CPU使用率为100%:

#-u:显示关于CPU使用情况的统计信息
#5:每隔 5 秒生成一次报告
#1:生成一次报告后退出
[root@localhost ~]# pidstat -u 5 1
Linux 3.10.0-1160.el7.x86_64 (localhost.localdomain)    09/27/2023      _x86_64_        (2 CPU)

10:28:54 AM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
10:28:59 AM     0     12349  100.00    0.00    0.00  100.00     0  stress
10:28:59 AM     0     12352    0.20    0.00    0.00    0.20     1  watch

Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
Average:        0     12349  100.00    0.00    0.00  100.00     -  stress
Average:        0     12352    0.20    0.00    0.00    0.20     -  watch

从这里可以看出,stress进程的CPU使用率为100%。

场景二:I/O密集型进程

首先,第一个终端运行stress命令模拟I/O压力,即不停地执行sync:

#1:要模拟一个I/O负载,1表示每个子进程将执行一个I/O操作
[root@localhost ~]# stress -i 1 --timeout 600
stress: info: [12755] dispatching hogs: 0 cpu, 1 io, 0 vm, 0 hdd

接着,第二个终端运行uptime查看平均负载的变化情况:

[root@localhost ~] watch -d uptime
Every 2.0s: uptime                                                                                   Wed Sep 27 14:46:04 2023

 14:46:04 up  5:11,  4 users,  load average: 1.25, 0.69, 0.32

最后,第三个终端运行mpstat查看CPU使用率的变化情况:

[root@localhost ~]# mpstat -P ALL 5 1
Linux 3.10.0-1160.el7.x86_64 (localhost.localdomain)    09/27/2023      _x86_64_        (2 CPU)

02:44:13 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
02:44:18 PM  all    2.30    0.00   47.90    0.00    0.00    0.00    0.00    0.00    0.00   49.80
02:44:18 PM    0    0.20    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00   99.60
02:44:18 PM    1    4.21    0.00   95.79    0.00    0.00    0.00    0.00    0.00    0.00    0.00

Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
Average:     all    2.30    0.00   47.90    0.00    0.00    0.00    0.00    0.00    0.00   49.80
Average:       0    0.20    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00   99.60
Average:       1    4.21    0.00   95.79    0.00    0.00    0.00    0.00    0.00    0.00    0.00

结论:从第二终端可以看出,1分钟的平均负载会慢慢增加到1.25。从第三个终端可以看出,其中一个CPU的系统CPU使用率升高到95.79,但%iowait没有变化,是因为stress使用sync()系统调用,它的作用是刷新缓冲区内存到磁盘。产生N个进程,每个进程循环调用sync将内存缓冲区内容写到磁盘上,产生IO压力。如果缓冲区内数据较少,写到磁盘中的数据也较少,不会产生IO压力。在SSD磁盘环境中尤为明显,很可能iowait总是0,却因为大量调用系统调用sync,导致系统CPU使用率sys升高。

        对于新安装的虚拟机,缓冲区可能比较小,无法产生大的IO压力,此时大部分被系统调用消耗掉,所以只有CPU使用率升高。解决方式是第一个终端使用stress的下一代stress-ng:

[root@localhost ~]# yum -y install stress-ng
#--hdd:读写临时文件
[root@localhost ~]# stress-ng -i 1 --hdd 1 --timeout 600
stress-ng: info:  [12268] dispatching hogs: 1 hdd, 1 io

第三个终端重新运行mpstat查看CPU使用率的变化情况:

[root@localhost ~]# mpstat -P ALL 5 1
Linux 3.10.0-1160.el7.x86_64 (localhost.localdomain)    10/07/2023      _x86_64_        (2 CPU)

04:24:55 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
04:25:00 PM  all    0.50    0.00    0.70   98.80    0.00    0.00    0.00    0.00    0.00    0.00
04:25:00 PM    0    0.60    0.00    1.00   98.40    0.00    0.00    0.00    0.00    0.00    0.00
04:25:00 PM    1    0.40    0.00    0.20   99.40    0.00    0.00    0.00    0.00    0.00    0.00

Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
Average:     all    0.50    0.00    0.70   98.80    0.00    0.00    0.00    0.00    0.00    0.00
Average:       0    0.60    0.00    1.00   98.40    0.00    0.00    0.00    0.00    0.00    0.00
Average:       1    0.40    0.00    0.20   99.40    0.00    0.00    0.00    0.00    0.00    0.00

结论:其中一个CPU的系统CPU使用率为0.2,而%iowait高达99.40,此时说明平均负载的升高是由于iowait的升高。

使用pidstat查看哪个进程导致CPU使用率sys高:

[root@localhost ~]# pidstat -u 5 1
Linux 3.10.0-1160.el7.x86_64 (localhost.localdomain)    10/07/2023      _x86_64_        (2 CPU)

04:25:18 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
04:25:23 PM     0         9    0.00    0.20    0.00    0.20     0  rcu_sched
04:25:23 PM     0     11749    0.00    0.20    0.00    0.20     0  kworker/0:0
04:25:23 PM     0     11933    0.00    0.20    0.00    0.20     0  kworker/u4:1
04:25:23 PM     0     11934    0.20    0.40    0.00    0.60     0  watch
04:25:23 PM     0     12269    0.00    7.34    0.00    7.34     0  stress-ng-hdd
04:25:23 PM     0     12270    0.00    0.40    0.00    0.40     1  stress-ng-io
04:25:23 PM     0     12306    0.20    0.40    0.00    0.60     0  pidstat

Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
Average:        0         9    0.00    0.20    0.00    0.20     -  rcu_sched
Average:        0     11749    0.00    0.20    0.00    0.20     -  kworker/0:0
Average:        0     11933    0.00    0.20    0.00    0.20     -  kworker/u4:1
Average:        0     11934    0.20    0.40    0.00    0.60     -  watch
Average:        0     12269    0.00    7.34    0.00    7.34     -  stress-ng-hdd
Average:        0     12270    0.00    0.40    0.00    0.40     -  stress-ng-io
Average:        0     12306    0.20    0.40    0.00    0.60     -  pidstat

从这里可以看出,是stress进程导致。

场景三:大量进程的场景

当系统中运行进程超出CPU运行能力时,就会出现等待CPU进程。

首先,第一个终端使用stress,模拟8个进程并发:

[root@localhost ~]# stress -c 8 --timeout 600
stress: info: [23779] dispatching hogs: 8 cpu, 0 io, 0 vm, 0 hdd

接着,第二个终端运行uptime查看平均负载的变化情况:

[root@localhost ~] watch -d uptime
Every 2.0s: uptime                                                                                   Thu Sep 28 09:06:02 2023

 09:06:02 up 23:31,  4 users,  load average: 8.09, 4.78, 2.04

最后,第三个终端运行pidstat查看进程情况:

[root@localhost ~]# pidstat -u 5 1
Linux 3.10.0-1160.el7.x86_64 (localhost.localdomain)    09/28/2023      _x86_64_        (2 CPU)

09:02:34 AM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
09:02:39 AM     0     23780   24.70    0.00    0.00   24.70     0  stress
09:02:39 AM     0     23781   24.70    0.00    0.00   24.70     0  stress
09:02:39 AM     0     23782   24.70    0.00    0.00   24.70     0  stress
09:02:39 AM     0     23783   24.70    0.00    0.00   24.70     1  stress
09:02:39 AM     0     23784   24.51    0.00    0.00   24.51     1  stress
09:02:39 AM     0     23785   24.90    0.00    0.00   24.90     1  stress
09:02:39 AM     0     23786   24.51    0.00    0.00   24.51     0  stress
09:02:39 AM     0     23787   24.70    0.00    0.00   24.70     1  stress

Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
Average:        0     23780   24.70    0.00    0.00   24.70     -  stress
Average:        0     23781   24.70    0.00    0.00   24.70     -  stress
Average:        0     23782   24.70    0.00    0.00   24.70     -  stress
Average:        0     23783   24.70    0.00    0.00   24.70     -  stress
Average:        0     23784   24.51    0.00    0.00   24.51     -  stress
Average:        0     23785   24.90    0.00    0.00   24.90     -  stress
Average:        0     23786   24.51    0.00    0.00   24.51     -  stress
Average:        0     23787   24.70    0.00    0.00   24.70     -  stress

结论:第二个终端可以看出,系统只有2个CPU比8个进程要少得多,所以系统CPU处于严重过载状态,平均负载高达8.09。第三个终端可以看出,由于8个进程具有相似的CPU使用率(%usr列),这表明它们在争抢2个CPU资源。

小结

归纳平均负载的理解,平均负载提供了一个快速查看系统整体性能的手段,反映了系统整体的负载情况。但只看平均负载并不能直接发现瓶颈具体出现在什么地方,所以在理解平均负载时,也要注意:

  • 平均负载高有可能是CPU密集型进程导致的;
  • 平均负载高并不一定代表CPU使用率高,还可能使I/O繁忙;
  • 当发现负载高,可以使用mpstat、pidstat等工具,辅助分析负载的来源。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Que_art

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值