Linux性能调优

当遇到 I/O 性能问题时,可以使用 iostat、iotop、 blktrace 等工具分析磁盘 I/O 的瓶颈。

查看/proc//下的的meminfo、status等文件可以具体才看到虚拟内存和实际物理内存 的使用情况。

查看cpu个数:grep 'model name' /proc/cpuinfo | wc -l

使用 uptime 命令查看三个不同时间间隔的平均值,如果 1 分钟、5 分钟、15 分钟的三个值基本相同,或者相差不大,那就说明系统负载很平稳。

案例

基于 Ubuntu 18.04,预先安装 stress 和 sysstat 包
apt install stress sysstat
sudo apt install stress

场景一:CPU 密集型进程

运行 stress 命令,模拟一个 CPU 使用率 100% 的场景:
在一个终端执行:stress --cpu 1 --timeout 600
在另一个终端执行:watch -d uptime
在第三个终端运行 mpstat 查看 CPU 使用率的变化情况:

# -P ALL 表示监控所有 CPU,后面数字 5 表示间隔 5 秒后输出一组数据
root@davinci-mini:/home/HwHiAiUser# mpstat -P ALL 5
Linux 4.19.90+ (davinci-mini)   12/23/21        _aarch64_       (8 CPU)

18:28:02     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
18:28:07     all   13.48    0.00    3.14    0.05    0.00    0.05    0.00    0.00    0.00   83.27
18:28:07       0   19.18    0.00    2.45    0.00    0.00    0.20    0.00    0.00    0.00   78.16
18:28:07       1   18.53    0.00    3.67    0.00    0.00    0.00    0.00    0.00    0.00   77.80
18:28:07       2   20.69    0.00    5.07    0.00    0.00    0.00    0.00    0.00    0.00   74.24
18:28:07       3   19.31    0.00    4.88    0.00    0.00    0.00    0.00    0.00    0.00   75.81
18:28:07       4   15.31    0.00    4.29    0.00    0.00    0.20    0.00    0.00    0.00   80.20
18:28:07       5   15.27    0.00    4.68    0.41    0.00    0.20    0.00    0.00    0.00   79.43
18:28:07       6    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
18:28:07       7    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

查看哪个进程导致了 CPU 使用率高,可以使用 pidstat 来查询:

# 间隔 5 秒后输出一组数据
root@davinci-mini:/home/HwHiAiUser# pidstat -u 5 1
Linux 4.19.90+ (davinci-mini)   12/23/21        _aarch64_       (8 CPU)

18:30:20      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
18:30:25        0        10    0.00    0.20    0.00    0.00    0.20     3  rcu_sched
18:30:25        0      1007    0.20    0.00    0.00    0.00    0.20     0  systemd-journal
18:30:25      100      1370    0.00    0.20    0.00    0.00    0.20     0  systemd-network
18:30:25        0      1883    0.00    0.20    0.00    0.00    0.20     2  drvlog_work_0
18:30:25     1000      2207    0.00    0.20    0.00    0.00    0.20     0  dmp_daemon
18:30:25        0      2352    2.59    1.59    0.00    0.00    4.18     5  analyzer
18:30:25        0      2406    0.20    0.00    0.00    0.00    0.20     3  alertmanager
18:30:25        0      2709    0.00    0.20    0.00    0.00    0.20     5  npu-smi
18:30:25        0      8552    0.20    0.40    0.00    0.00    0.60     1  pidstat
18:30:25        0     10352    0.00    0.20    0.00    0.00    0.20     5  kworker/5:1H-kblockd
18:30:25        0     12070    8.37    0.80    0.00    0.00    9.16     2  java
18:30:25        0     14614    0.20    1.20    0.00    0.00    1.39     4  stream
18:30:25        0     24877    0.00    0.20    0.00    0.00    0.20     0  kworker/0:2-events
18:30:25        0     25422   93.43   20.32    0.00    0.00  100.00     3  vmr-lite

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

运行 stress 命令,但这次模拟 I/O 压力,即不停地执行 sync:
在一个终端执行:stress -i 1 --timeout 600
在第二个终端运行 uptime 查看平均负载的变化情况:watch -d uptime
第三个终端运行 mpstat 查看 CPU 使用率的变化情况:

# 显示所有 CPU 的指标,并在间隔 5 秒输出一组数据
mpstat -P ALL 5 1

可以看到iowait导致平均负载升高

哪个进程,导致 iowait 这么高呢?我们还是用 pidstat 来查询:

 # 间隔 5 秒后输出一组数据,-u 表示 CPU 指标
pidstat -u 5 1

可以发现,是 stress 进程导致的。

场景三:大量进程的场景

当系统中运行进程超出 CPU 运行能力时,就会出现等待 CPU 的进程。
我们使用 stress,但这次模拟的是 8 个进程: stress -c 8 --timeout 600

由于系统只有 2 个 CPU,明显比 8 个进程要少得多,因而,系统的 CPU 处于严重过载状态, 平均负载高达 7.97:

uptime
..., load average: 7.97, 5.93, 3.02

接着再运行 pidstat 来看一下进程的情况:

 # 间隔 5 秒后输出一组数据,-u 表示 CPU 指标
pidstat -u 5 1

8 个进程在争抢 2 个 CPU,每个进程等待 CPU 的时间(也就是代码块中的 %wait 列)高达 75%。这些超出 CPU 计算能力的进程,最终导致 CPU 过载。

小结

平均负载高有可能是 CPU 密集型进程导致的;
平均负载高并不一定代表 CPU 使用率高,还有可能是 I/O 更繁忙了;
当发现负载高的时候,你可以使用 mpstat、pidstat 等工具,辅助分析负载的来源。

上下文切换导致负载高

vmstat是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也常用来分析 CPU 上下文切换和中断的次数。

HwHiAiUser@davinci-mini:~$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 2297856 1048880 1900820    0    0     1    18    2    0 19  4 77  0  0
 3  0      0 2344436 1048880 1900856    0    0     0    85 25325 50968 22  5 74  0  0
 6  0      0 2424336 1048888 1900860    0    0     0   160 25343 49313 15  4 81  0  0
 2  0      0 2433636 1048888 1900868    0    0     0   100 24543 48054 23  4 72  0  0
 3  0      0 2437372 1048888 1900880    0    0     0    95 23893 48505 21  4 75  0  0

cs(context switch)是每秒上下文切换的次数。
in(interrupt)则是每秒中断的次数。
r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
b(Blocked)则是处于不可中断睡眠状态的进程数。

vmstat 只给出了系统总体的上下文切换情况,要想查看每个进程的详细情况,就需要使用我们 前面提到过的 pidstat 了。给它加上 -w 选项,你就可以查看每个进程上下文切换的情况了。

HwHiAiUser@davinci-mini:~$ pidstat -w 5
Linux 4.19.90+ (davinci-mini)   12/23/21        _aarch64_       (8 CPU)

18:57:58      UID       PID   cswch/s nvcswch/s  Command
18:58:03        0         1      0.20      0.00  systemd
18:58:03        0         9     10.76      0.80  ksoftirqd/0
18:58:03        0        10    113.55      0.00  rcu_sched
18:58:03        0        12      0.40      0.00  migration/0
18:58:03        0        15      0.40      0.00  migration/1
18:58:03        0        16      0.40      0.00  ksoftirqd/1

这个结果中有两列内容是我们的重点关注对象。
一个是 cswch ,表示每秒自愿上下文切换 (voluntary context switches)的次数。
另一个则是 nvcswch ,表示每秒非自愿上下文切换 (non voluntary context switches)的次数。

案例

使用 sysbench 来模拟系统多线程调度切换的情况,预先安装 sysbench 和 sysstat 包,如 apt install sysbench sysstat

在第一个终端里运行 sysbench ,模拟系统多线程调度的瓶颈:

# 以 10 个线程运行 5 分钟的基准测试,模拟多线程切换的问题 
sysbench --threads=10 --max-time=300 threads run

在第二个终端运行 vmstat ,观察上下文切换情况:

# 每隔 1 秒输出 1 组数据(需要 Ctrl+C 才结束)
$ vmstat 1

你应该可以发现,cs 列的上下文切换次数从之前的 35 骤然上升到了 139 万。同时,注意观察 其他几个指标:
r 列:就绪队列的长度已经到了 8,远远超过了系统 CPU 的个数 2,所以肯定会有大量的 CPU 竞争。
us(user)和 sy(system)列:这两列的 CPU 使用率加起来上升到了 100%,其中系统 CPU 使用率,也就是 sy 列高达 84%,说明 CPU 主要是被内核占用了。
in 列:中断次数也上升到了 1 万左右,说明中断处理也是个潜在的问题。

综合这几个指标,我们可以知道,系统的就绪队列过长,也就是正在运行和等待 CPU 的进程数过多,导致了大量的上下文切换,而上下文切换又导致了系统 CPU 的占用率升高。

那么到底是什么进程导致了这些问题呢?
在第三个终端再用 pidstat 来看一下, CPU 和进程上下文切换的情况:

# -w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标
# -wt 参数表示输出线程的上下文切换指标
HwHiAiUser@davinci-mini:~$ pidstat -w -u 1
Linux 4.19.90+ (davinci-mini)   12/23/21        _aarch64_       (8 CPU)

19:05:01      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
19:05:02        0        10    0.00    0.98    0.00    0.00    0.98     1  rcu_sched
19:05:02        0      1483    0.98    0.00    0.00    0.00    0.98     3  prometheus
19:05:02        0      1904    5.88    0.00    0.00    0.00    5.88     1  java
19:05:02        0      2452    1.96    2.94    0.00    0.00    4.90     1  stream
19:05:02        0     21148   82.35   22.55    0.00    0.00  100.00     5  vmr-lite
19:05:02        0     22155   99.02   11.76    0.00    0.00  100.00     1  analyzer
19:05:02     1000     23640    0.98    0.98    0.00    0.00    1.96     3  pidstat

中断

从 /proc/interrupts 这个只读文件中读取。/proc 实际上是 Linux 的一个虚拟文 件系统,用于内核空间与用户空间之间的通信。/proc/interrupts 就是这种通信机制的一部分, 提供了一个只读的中断使用情况。

# -d 参数表示高亮显示变化的区域
$ watch -d cat /proc/interrupts

小结:

首先通过uptime查看系统负载,然后使用mpstat结合pidstat来初步判断到底 是cpu计算量大还是进程争抢过大或者是io过多,接着使用vmstat分析切换次数,以及切换 类型,来进一步判断到底是io过多导致问题还是进程争抢激烈导致问题。

# 并发 10 个请求测试 Nginx 性能,总共测试 100 个请求
$ ab -c 10 -n 100 http://192.168.0.10:10000/

你可能感兴趣的:(Linux性能调优)