Linux 性能观测之CPU平均负载

2024-08-29 17:54:20 浏览数 (2)

写在前面

  • 博文内容涉及 Linux 平均负载认知
  • 以及造成平均负载波动的场景认知:
    • CPU 密集型进程
    • I/O 密集型进程
    • 大量进程
  • 理解不足小伙伴帮忙指正 :),生活加油

99%的焦虑都来自于虚度时间和没有好好做事,所以唯一的解决办法就是行动起来,认真做完事情,战胜焦虑,战胜那些心里空荡荡的时刻,而不是选择逃避。不要站在原地想象困难,行动永远是改变现状的最佳方式


Linux 平均负载指标可以说是最直观的查看 Linux 性能负载的指标,可以对 CPU 性能有直观的体现,性能调优大神 Brendan Gregg 在 Linux 60s 性能分析中最先讲到的工具为 uptime ,一起来看下如何理解这些平均负载指标

平均负载

查看 Linux 平均负载的命令有两个,一个使用 uptime 命令

代码语言:javascript复制
liruilong@liruilongs:~$ uptime
 19:35:03 up 1 day,  5:36,  0 users,  load average: 0.52, 0.58, 0.59
liruilong@liruilongs:~$

在实际使用中可以配合 watch -d 命令实时监控

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$watch -d uptime 

另一个是是使用 top 命令来查看,实际上显示的也是 uptime 输出的数据

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$top

top - 11:33:19 up 1 min,  1 user,  load average: 0.88, 0.40, 0.15

load average 对应的值即为平均负载,先来看下帮助文档如何描述 平均负载

uptime 命令用于显示系统已运行的时间,并提供系统负载平均值的信息。以下是 uptime 命令提供的信息解释:

代码语言:javascript复制
┌──[liruilong@liruilongs.github.io]-[~]
└─$man uptime
UPTIME(1)                                           User Commands                                           UPTIME(1)

NAME
       uptime - Tell how long the system has been running.

SYNOPSIS
       uptime [options]

DESCRIPTION
       uptime  gives a one line display of the following information.  The current time, how long the system has been
       running, how many users are currently logged on, and the system load averages for the past 1, 5, and  15  min‐
       utes.

       This is the same information contained in the header line displayed by w(1).

       System  load  averages  is  the  average  number of processes that are either in a runnable or uninterruptable
       state.  A process in a runnable state is either using the CPU or waiting to use the CPU.  A process  in  unin‐
       terruptable  state is waiting for some I/O access, eg waiting for disk.  The averages are taken over the three
       time intervals.  Load averages are not normalized for the number of CPUs in a system, so a load average  of  1
       means a single CPU system is loaded all the time while on a 4 CPU system it means it was idle 75% of the time.
       ......................................

uptime 可以快速查看当前系统时间以及运行时间,总的登录用户, 以及平均负载

  • 当前时间:显示执行uptime命令时的系统当前时间。
  • 系统运行时间:显示系统自上次引导或重新启动以来的运行时间。以"X天X小时X分钟"的格式显示。
  • 用户数量:表示当前登录到系统的用户数量
  • 系统负载平均值:显示过去1分钟、5分钟和15分钟系统负载平均值。负载平均值代表处于运行状态或等待运行状态的平均进程数量(平均活跃进程数)。它指示系统的活动水平和资源利用程度。负载平均值并不针对系统中的CPU核数进行归一化,它和 CPU 使用率并没有直接关系

如何理解平均负载指标

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~]
└─$uptime
 11:14:26 up 16 min,  1 user,  load average: 21.37, 18.64, 16.25

这些数字包含了想要在 CPU 上运行的进程( ps 命令处于 R 状态(Running 或 Runnable)的进程),同时也包含了阻塞在不可中断IO(通常是磁盘 I/O, ps 命令处于 D 状态(Uninterruptible Sleep,也称为 Disk Sleep)的进程)上的进程。这给出了一个高层次视角的资源负载(或者说资源需求)

当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现磁盘数据与进程数据不一致的问题.所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制

3个数字分别是指数衰减的1分钟/5分钟/15分钟滑动窗累积值(可以直接理解为 单位时间内的活跃进程数)。通过这3个值可以大致了解负载随时间变化的情况。平均负载要结合CPU 逻辑核数来观察。

快速查看CPU核数可以通过top命令然后按1键查看

代码语言:javascript复制
top - 11:21:36 up 23 min,  1 user,  load average: 22.36, 19.03, 17.14
Tasks: 443 total,   5 running, 438 sleeping,   0 stopped,   0 zombie
%Cpu0  :  6.4 us,  5.4 sy,  0.0 ni, 77.9 id,  0.0 wa,  4.4 hi,  5.9 si,  0.0 st
%Cpu1  :  9.2 us, 12.2 sy,  0.0 ni, 71.9 id,  3.6 wa,  2.0 hi,  1.0 si,  0.0 st
%Cpu2  :  4.8 us,  3.6 sy,  0.0 ni, 68.8 id,  4.8 wa, 18.0 hi,  0.0 si,  0.0 st
%Cpu3  :  4.5 us,  5.5 sy,  0.0 ni, 72.7 id,  2.7 wa,  0.5 hi, 14.1 si,  0.0 st
MiB Mem :  15730.5 total,   7489.9 free,   6823.5 used,   1417.2 buff/cache
MiB Swap:   2068.0 total,   2068.0 free,      0.0 used.   8496.2 avail Mem

或者查看 CPU 信息

代码语言:javascript复制
liruilong@liruilongs:~$ grep 'model name' /proc/cpuinfo | wc -l
8

top命令然后按1键的基础上可以按 t 键对数据进行可视化展示,可以直观的看到 CPU 的使用率。

代码语言:javascript复制
top - 11:22:26 up 24 min,  1 user,  load average: 15.02, 17.58, 16.74
Tasks: 449 total,  19 running, 430 sleeping,   0 stopped,   0 zombie
%Cpu0  :  24.5/37.1   62[|||||||||||||||||||||||||||||||||||||||||||||||||||||||||                                    ]
%Cpu1  :  15.5/28.0   43[||||||||||||||||||||||||||||||||||||||||                                                     ]
%Cpu2  :  37.9/61.1   99[|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ]
%Cpu3  :  15.8/49.7   66[|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||                                ]

平均负载为多少时合理,上面的例子显示负载最近有大幅的提升。一般情况下(还受到其他因素的影响,I/O 操作等),负载数与系统 CPU 核数的关系可以用以下规则来理解:

如果负载数小于 CPU 核数的70-80%:这通常表示系统的负载较轻,有足够的处理能力来处理所有的任务。系统响应时间较短,性能较好。

如果负载数接近或超过 CPU 核数的100%:这表示系统的负载很高,正在接近或达到其处理能力的极限。系统可能会出现延迟或变慢的情况,响应时间变长。

如果负载数远远超过 CPU 核数的100%:这表示系统的负载非常高,超过了系统的处理能力。系统可能会出现严重的延迟,甚至崩溃或无法响应。

平均负载有三个数值,到底该参考哪一个呢?

负载的平均值值得在排障过程中被首先进行检查,以确认性能问题是否还存在。在一个容错的环境中,一台存在性能问题的服务器,在你登录到机器上时,也许已经自动从服务列表中下线了。

一个较高的 15分钟负载与一个较低的1分钟负载同时出现,可能意味着已经错过了问题发生的现场。, 反之, 如果 1 分钟的负载 远大于 15 分钟的负载,就说明最近 1 分钟的负载在增加,这种增加有可能只是临时性的,也有可能还会持续增加下去,所以就需要持续观察。一旦 1 分钟的平均负载接近或超过了 CPU 的个数,就意味着系统正在发生过载的问题,CPU 可能已经处于饱和状态

代码语言:javascript复制
┌──[root@vms100.liruilongs.github.io]-[~]
└─$uptime
 11:33:45 up 35 min,  1 user,  load average: 1.39, 6.06, 11.64
┌──[root@vms100.liruilongs.github.io]-[~]
└─$ 

平均负载与 CPU 使用率

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

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

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

平均负载指标理解案例

这里复现一下提到了三种不同情况,这是当前正常环境的 平均负载情况

代码语言:javascript复制
Every 2.0s: uptime                                                            Thu Aug 22 20:30:14 2024

 20:30:14 up 10 min,  4 users,  load average: 1.97, 2.77, 1.71

CPU 密集型

通过 stress 命令来模拟 CPU 密集型操作,比如一些 AI 方面的预测,模型训练,这里的 CPU 1 为 对单个CPU 逻辑核进行密集性运算模拟,stress 命令是一个非常有用的 Linux 系统压力测试工具,它可以帮助开发者、系统管理员或测试人员对系统进行压力测试和性能评估。

代码语言:javascript复制
┌──[root@vms100.liruilongs.github.io]-[~]
└─$stress --cpu 1 --timeout 300
stress: info: [8467] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd

查看 平均负载情况,5分钟内的平均负载升高

代码语言:javascript复制
Every 2.0s: uptime                                                            Thu Aug 22 20:26:08 2024

 20:26:08 up 6 min,  4 users,  load average: 3.41, 2.65, 1.32

通过 mpstat 命令来查看 CPU 负载信息,mpstat 命令是 Linux 系统上的一个重要的性能监控工具,它用于报告各个 CPU 的统计信息。

代码语言:javascript复制
┌──[root@vms100.liruilongs.github.io]-[~]
└─$ mpstat -P ALL 5
Linux 5.4.266-1.el7.elrepo.x86_64 (vms100.liruilongs.github.io)         2024年08月22日  _x86_64_     (4 CPU)

20时22分25秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
20时22分30秒  all   30.43    0.00    2.95    0.00    0.00    0.78    0.00    0.00    0.00   65.84
20时22分30秒    0    5.53    0.00    3.62    0.00    0.00    1.70    0.00    0.00    0.00   89.15
20时22分30秒    1    5.24    0.00    3.56    0.00    0.00    0.63    0.00    0.00    0.00   90.57
20时22分30秒    2  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
20时22分30秒    3    7.66    0.00    4.97    0.00    0.00    0.83    0.00    0.00    0.00   86.54

可以看到 对于 CPU 逻辑核 2 两个异常的指标:

  • CPU用户态使用率(%usr) 为 100%
  • CPU 空闲率(%idle) 为 0%

在实际场景中,这种单个CPU 饱和的情况很少遇到,即便是遇到了,可以从下面的场景排查:

  • 一是要考虑是否代码中指定了CPU逻辑核数,需要排查代码逻辑
  • 二是对运行进程配置了CPU 亲和性,权重,需要排查服务启动文件,或者Cgroup(cpuset.cpus)等资源控制文件

大量进程的场景

这是相对常见的一种异常场景,大量的进程对CPU核内存都有影响,之前在生产中有遇到一次,代码BUG,建立了无数个FTP链接导致系统CPU核内存持续飙升。

这里我们同样使用 stress 模拟

代码语言:javascript复制
┌──[root@vms100.liruilongs.github.io]-[~]
└─$stress -c 8 --timeout 600
stress: info: [18185] dispatching hogs: 8 cpu, 0 io, 0 vm, 0 hdd

可以看到 平均负载飙升,已经处于过度饱和状态

代码语言:javascript复制
Every 2.0s: uptime                                                            Thu Aug 22 21:02:48 2024

 21:02:48 up 8 min,  4 users,  load average: 5.71, 2.25, 0.97

通过 mpstat 观测CPU 使用率和空闲度,可以很直观的看到

代码语言:javascript复制
┌──[root@vms100.liruilongs.github.io]-[~]
└─$mpstat -P ALL 5
Linux 5.4.266-1.el7.elrepo.x86_64 (vms100.liruilongs.github.io)         2024年08月22日  _x86_64_        (4 CPU)

21时02分27秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
21时02分32秒  all   96.06    0.00    3.24    0.00    0.00    0.69    0.00    0.00    0.00    0.00
21时02分32秒    0   93.18    0.00    4.26    0.00    0.00    2.56    0.00    0.00    0.00    0.00
21时02分32秒    1   96.63    0.00    2.95    0.00    0.00    0.42    0.00    0.00    0.00    0.00
21时02分32秒    2   97.88    0.00    2.12    0.00    0.00    0.00    0.00    0.00    0.00    0.00
21时02分32秒    3   96.13    0.00    3.66    0.00    0.00    0.22    0.00    0.00    0.00    0.00

对于这种问题的定位可以直接使用 top 命令查看每个逻辑核的 CPU 使用情况,以及进程使用情况。

代码语言:javascript复制
top - 21:06:03 up 11 min,  4 users,  load average: 6.86, 4.41, 2.09
Tasks: 274 total,   9 running, 176 sleeping,   0 stopped,   0 zombie
%Cpu0  :  85.5/11.2   97[|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||   ]
%Cpu1  :  92.4/6.4    99[||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||  ]
%Cpu2  :  93.3/6.7   100[||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||]
%Cpu3  :  89.3/9.8    99[||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ]

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME  COMMAND
 25031 root      20   0    7320     96      0 R  51.0  0.0   0:15.58 stress
 25029 root      20   0    7320     96      0 R  45.0  0.0   0:15.80 stress
 25034 root      20   0    7320     96      0 R  41.7  0.0   0:15.28 stress
 25035 root      20   0    7320     96      0 R  37.7  0.0   0:14.60 stress
 25033 root      20   0    7320     96      0 R  35.4  0.0   0:14.84 stress
 25032 root      20   0    7320     96      0 R  34.4  0.0   0:14.74 stress
 25030 root      20   0    7320     96      0 R  32.8  0.0   0:14.77 stress
 25036 root      20   0    7320     96      0 R  32.1  0.0   0:14.86 stress
  1043 root      20   0 1348748 102384  48352 S  17.5  1.7   0:33.75 dockerd
  1962 root      20   0 10.696g 176412 107048 S  11.3  2.9   0:55.40 etcd
  1223 root      20   0 1019220  49628  27312 S  10.3  0.8   0:19.37 cri-dockerd
  1667 root      20   0 1806176 1.020g  72460 S   5.6 17.5   1:07.65 kube-apiserver
   943 root      20   0 1763192 112924  64100 S   5.0  1.8   0:22.20 kubelet
  3301 root      20   0 1673552  69068  46116 S   2.3  1.1   0:19.33 calico-node

生产场景中,可能进程特别多,但是每个进程CPU 使用率很小,我们可以通过下面的命令进行排查。分组统计当前系统所有进程

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$ps aux | awk '{print $11}' | sort | uniq -c | sort -nr | head -n 10
      9 stress
      5 /usr/bin/dbus-daemon
      5 nginx:
      4 /usr/bin/gjs
      4 sudo
      3 /usr/local/uniagentd/bin/uniagentd
      3 /usr/libexec/gnome-session-binary
      2 /usr/sbin/xrdp-sesman
      2 /usr/sbin/xrdp
      2 /usr/sbin/kerneloops
┌──[root@liruilongs.github.io]-[~] 
└─$

IO 密集型

对于IO 密集型,有两种不同的情况,下面为一个生产环境中 IO 密集型场景通过 mpstat 观测指标,可以看到,用户态(%usr )和内核态(%sys)的 CPU 使用率相对较少,但是CPU 等待IO 完成占比(%iowait) 相对较大,所以整体的CPU空闲率(%idle)较低

代码语言:javascript复制
┌──[root@vms100.liruilongs.github.io]-[~]
└─$mpstat -P ALL 1
Linux 4.18.0-477.27.1.el8_8.x86_64 (vms100.liruilongs.github.io)        2024年01月14日  _x86_64_        (4 CPU)
11时43分36秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11时43分37秒  all   12.89    0.00   14.84   50.00    6.25    4.30    0.00    0.00    0.00   11.72
11时43分37秒    0   21.57    0.00   15.69   50.98    5.88    1.96    0.00    0.00    0.00    3.92
11时43分37秒    1   12.68    0.00    9.86   76.06    1.41    0.00    0.00    0.00    0.00    0.00
11时43分37秒    2   12.70    0.00   25.40    3.17   17.46    0.00    0.00    0.00    0.00   41.27
11时43分37秒    3    7.04    0.00    9.86   64.79    1.41   14.08    0.00    0.00    0.00    2.82
.........

stress 模拟负载

当前的系统负载

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$uptime 
 15:15:01 up  1:01,  3 users,  load average: 0.00, 0.09, 0.41
┌──[root@liruilongs.github.io]-[~] 
└─$

模拟命令

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$stress --hdd 5 --timeout 600
stress: info: [5778] dispatching hogs: 0 cpu, 0 io, 0 vm, 5 hdd

查看系统平均负载上升

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$uptime 
 15:32:40 up  1:19,  3 users,  load average: 6.10, 5.63, 3.80

观测CPU 性能情况,可以看到,当前空闲率(%idle)较低,CPU使用主要集中在 不可中断IO(%iowait)等待

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$mpstat -P ALL 5
Linux 5.15.0-112-generic (liruilongs.github.io)  2024年08月24日  _x86_64_ (4 CPU)

15时23分21秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
15时23分26秒  all    0.91    0.00    4.21   84.91    0.00    0.11    0.00    0.00    0.00    9.86
15时23分26秒    0    1.25    0.00    4.18   71.82    0.00    0.21    0.00    0.00    0.00   22.55
15时23分26秒    1    0.65    0.00    3.01   92.26    0.00    0.00    0.00    0.00    0.00    4.09
15时23分26秒    2    0.85    0.00    5.33   89.55    0.00    0.00    0.00    0.00    0.00    4.26
15时23分26秒    3    0.86    0.00    4.32   86.39    0.00    0.22    0.00    0.00    0.00    8.21
............
┌──[root@liruilongs.github.io]-[~] 
└─$

通过 vmstat 查看系统整体性能:

CPU 利用率主要集中在内核态和等待 I/O 操作(wa),空闲率较低(id),表明系统正在进行大量的 I/O 操作,系统正在进行大量的磁盘写入操作(bo)

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b    交换    空闲    缓冲     缓存   si   so    bi    bo   in   cs us sy id wa st
 1  6      0 2205568 193376 4205452    0    0    49 30931  945 2194  2  8 81 10  0
 0  6      0 2971176 193388 3439780    0    0     0 354446 1162 1256  1  8 10 81  0
 0  6      0 2769100 193396 3634488    0    0     0 363526 1031 1031  1  8 15 76  0
 0  6      0 2726372 193408 3679292    0    0     0 356962 1034  988  1  8 11 80  0
 1  5      0 2587760 193416 3818884    0    0     0 366231 1052 1100  0  7  7 87  0
c^C

iostat 命令的输出,我们只看到对应的硬盘设备,

据 iostat 命令的输出,可以对系统的 I/O 性能进行以下分析:

  • w_await: 较高的写入等待时间通常意味着磁盘 I/O 压力较大,可能成为系统性能瓶颈,写入平均等待时间为 2.55 - 261.61 ms
  • util: 磁盘利用率为 69.11% - 101.84%
  • aqu-sz: 磁盘的平均请求队列长度,队列长度越长,意味着磁盘 I/O 操作的并行度越高,可能导致更长的等待时间
代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$iostat  -xk 5 vda
Linux 5.15.0-112-generic (liruilongs.github.io)  2024年08月24日  _x86_64_ (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           1.58    0.01    7.55   12.14    0.00   78.72

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
vda              3.84    179.42     1.54  28.60    1.04    46.68 7803.21 128712.72   524.63   6.30    2.55    16.49    0.00      0.00     0.00   0.00    0.00     0.00    2.68    0.07   19.87  69.11


avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.63    0.00    3.26   87.69    0.00    8.41

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
vda              0.00      0.00     0.00   0.00    0.00     0.00  325.40 367139.20     7.00   2.11  217.83  1128.27    0.00      0.00     0.00   0.00    0.00     0.00    0.40    0.50   70.88 100.96


avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.68    0.00    9.37   80.69    0.00    9.26

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
vda              0.00      0.00     0.00   0.00    0.00     0.00  325.80 351251.20    20.20   5.84  261.61  1078.12    0.00      0.00     0.00   0.00    0.00     0.00    0.40    0.00   85.23 101.84

^C
┌──[root@liruilongs.github.io]-[~] 
└─$

从以上分析可以得出以下结论:

系统正在进行大量的磁盘写入操作,导致 CPU 资源大量消耗在等待 I/O 操作上。磁盘利用率非常高(%util),接近 100%,表明磁盘可能是系统的瓶颈所在。

实际上这里还有一种情况,这里我们用 fio 进行测试, 通过 fio 异步IO 实际测试发现,虽然平均负载上去了,但是 CPU 等待IO 完成的占比一直上不去,反而是内核态的 CPU 使用率飙升。

fio 测试命令

代码语言:javascript复制
┌──[root@vms100.liruilongs.github.io]-[~]
└─$fio --name=randwrite --ioengine=libaio --iodepth=1 --rw=randwrite --bs=4K --direct=1 --size=11512M --numjobs=6 --group_reporting --filename=/tmp/testfile

参数说明

  • --ioengine=libaio: 使用 libaio 异步 I/O 引擎进行 I/O 操作。这个引擎可以提高 I/O 并行度。
  • --iodepth=1: 设置 I/O 深度为 1,即每个 I/O 请求同时只有 1 个在处理。
  • --rw=randwrite: 指定 I/O 模式为随机写入。
  • --bs=4K: 设置块大小为 4KB。
  • --direct=1: 使用直接 I/O,绕过文件系统缓存。
  • --size=11512M: 总共要写入的数据量为 11.5GB。
  • --numjobs=6: 启动 6 个并发的写入任务。
  • --group_reporting: 合并输出结果,以便更好地观察整体性能。
  • --filename=/tmp/testfile: 指定写入的文件路径为 /tmp/testfile。

平均负载

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$uptime 
 16:14:51 up  2:01,  3 users,  load average: 4.00, 1.19, 0.83

iostat 输出,可以看到 avgqu-sz 值不是特别大,且请求等待时间 awaitsvctm 所花费时间差距较小,利用率%util为100%, 设备趋于饱和,但是 等待IO 指标体现不明显。这里的瓶颈实际上在磁盘

代码语言:javascript复制
┌──[root@vms100.liruilongs.github.io]-[~]
└─$iostat  -dk -x 5
Linux 5.4.266-1.el7.elrepo.x86_64 (vms100.liruilongs.github.io)         2024年08月22日  _x86_64_        (4 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.40    1.00 8027.80    54.40 32112.80     8.01     0.07    0.18    0.20    0.18   0.12  99.56

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     3.00    0.00 8068.60     0.00 32352.90     8.02     0.04    0.18    0.00    0.18   0.12  99.62
.......

查看CPU 相关信息,可以看到 使用率大的部分在内核态(%sys),而不是我们希望的 IO 等待(%iowait)

代码语言:javascript复制
┌──[root@vms100.liruilongs.github.io]-[~]
└─$mpstat  5
Linux 5.4.266-1.el7.elrepo.x86_64 (vms100.liruilongs.github.io)         2024年08月22日  _x86_64_        (4 CPU)

21时12分46秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
21时12分51秒  all    9.10    0.00   43.52    0.12    0.00    7.89    0.00    0.00    0.00   39.38
21时12分56秒  all    9.52    0.00   42.50    0.18    0.00    8.70    0.00    0.00    0.00   39.11
21时13分01秒  all    7.65    0.00   43.98    0.00    0.00    7.42    0.00    0.00    0.00   40.95
......

这里我换一组参数

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$fio --name=seq-read --rw=read --bs=4k --size=1G --numjobs=4 --runtime=6000 --output-format=json

查看平均负载指标上升

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$uptime 
 16:34:28 up  2:20,  3 users,  load average: 1.44, 1.27, 1.85

cpu 性能指标,这时候的指标信息可以看到 CPU 负载主要集中在 等待IO(%iowait),空闲率(%idle)很低,而不是上面的 内核态(%sys)

代码语言:javascript复制
┌──[root@liruilongs.github.io]-[~] 
└─$mpstat  1 
Linux 5.15.0-112-generic (liruilongs.github.io)  2024年08月24日  _x86_64_ (4 CPU)

16时33分43秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
16时33分44秒  all    3.55    0.00    5.33   90.10    0.00    0.25    0.00    0.00    0.00    0.76
16时33分45秒  all    6.65    0.00    7.14   84.98    0.00    0.49    0.00    0.00    0.00    0.74
16时33分46秒  all    2.53    0.00    5.82   91.65    0.00    0.00    0.00    0.00    0.00    0.00
16时33分47秒  all    3.79    0.00    5.56   89.14    0.00    0.25    0.00    0.00    0.00    1.26
16时33分48秒  all    7.56    0.00    4.03   71.54    0.00    0.25    0.00    0.00    0.00   16.62

IO 相关指标,磁盘使用率很高,但是IO写入队列不长

代码语言:javascript复制
Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
vda           2600.00 663552.00     0.00   0.00    2.44   255.21    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    6.34  88.00


Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
vda           1401.00 358400.00     0.00   0.00    5.30   255.82    1.00      4.00     6.00  85.71    2.00     4.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    7.43  97.60


Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
vda           1401.00 358400.00     0.00   0.00    5.37   255.82    2.00     32.00     0.00   0.00  322.50    16.00    0.00      0.00     0.00   0.00    0.00     0.00    2.00    0.00    8.16  93.20

这里有个问题,为什么 fio 模拟IO负载,两次的的指标值不一样?欢迎小伙伴留言讨论 ^_^

  • 第一次平均负载升高原因是 内核态CPU使用率影响
  • 第二次平局负载升高原因是 不可中断IO等待CPU使用率影响

实际上对于 IO 密集型,IO 模式,深度等不同,对平均负载影响也不同,

区别:

I/O 模式:

  • fio --name=randwrite 是随机写入,对 CPU 利用率有较大影响,CPU 主要消耗在内核态处理 I/O 请求。
  • fio --name=seq-read 是顺序读取,对 CPU 消耗相对较小,更多的时间消耗在 I/O 等待上。

I/O 深度:

  • fio --name=randwrite 设置了 iodepth=1,即单个任务的 I/O 深度较浅,需要 CPU 频繁切换上下文。
  • fio --name=seq-read 使用了默认的 I/O 深度,可能会有更多 I/O 请求在队列中等待。

I/O 引擎:

  • fio --name=randwrite 使用了 libaio 异步 I/O 引擎,可以更好地利用多核 CPU 并行处理 I/O。可能产生更高的 I/O 负载和吞吐量
  • fio --name=seq-read 使用了默认的同步 I/O 引擎,对 CPU 的利用率可能不如异步引擎。

关于 Linux 平均负载就可以小伙伴分享到这里,理解不足小伙伴帮忙指正,希望通过对平均负载指标的理解,我们可以快速定位问题。

博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知 :)

《Linux性能优化》中文版

《BPF Performance Tools》

极客时间 《Linux 性能优化实战》

© 2018-2024 liruilonger@gmail.com, 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)

0 人点赞