定位性能问题常用方法:系统负载,CPU与进程【转】

转自:https://blog.csdn.net/helowken2/article/details/107478974?spm=1001.2014.3001.5502

实验环境
OS:Ubuntu 18.04
CPU:2 Cores
Memory:4G

查看OS版本
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

查看CPU个数
$ cat /proc/cpuinfo | grep "model name"
model name      : Intel(R) Core(TM) i5-8350U CPU @ 1.70GHz
model name      : Intel(R) Core(TM) i5-8350U CPU @ 1.70GHz

查看内存信息
$ free -m
              total        used        free      shared  buff/cache   available
Mem:           3944         128        3309           0         506        3601
Swap:          2047

查看OS信息
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

查看系统信息
$ uname -a
Linux aaa_ubuntu 4.15.0-112-generic #113-Ubuntu SMP Thu Jul 9 23:41:39 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

查看平均负载
显示的数值为最近1分钟,5分钟,15分钟内的变化,从中可以看出趋势。

$ uptime
 17:03:14 up 13 min,  1 user,  load average: 0.00, 0.02, 0.03

或者用 top 命令:

持续观察变化(或者使用 top 命令):

$ watch -d uptime

平均负载越高,说明系统越繁忙,但系统繁忙不代表CPU繁忙。

说明
平均负载:单位时间内,系统处于可运行状态和不可中断状态的平均活跃进程数。
可运行状态:正在使用CPU或等待使用CPU(R状态,Running or Runnable)
不可中断状态:处于内核关键流程且不可被中断,最常见为等待硬件响应(D状态,Uninterruptible sleep)

理想状态下,系统多少CPU就同时运行多少进程,平均负载 <= CPU Core数(一般在平均负载到达70%时要留意)。(但我不清楚在开启了超线程之后,这个公式应该进行怎样的调整)。
当平均负载 > CPU Core数时,就会发生超载。

平均负载升高的原因
存在CPU密集型进程
特征:CPU使用率很高

上图显示系统负载接近3, 2个 cpu 使用率都为100%,其中有3个进程占用了大量 cpu

$ mpstat -P ALL 1
Linux 4.15.0-112-generic (aaa_ubuntu)   08/15/2020      _x86_64_        (2 CPU)

06:02:55 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
06:02:56 PM  all  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:02:56 PM    0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:02:56 PM    1  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00

06:02:56 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
06:02:57 PM  all  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:02:57 PM    0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:02:57 PM    1  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00

06:02:57 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
06:02:58 PM  all  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:02:58 PM    0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:02:58 PM    1  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00

上图显示 每个 cpu 的使用率,跟 top 显示的一致。

$ pidstat -u 1
Linux 4.15.0-112-generic (aaa_ubuntu)   08/15/2020      _x86_64_        (2 CPU)

06:03:21 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
06:03:22 PM  1000      2902   70.30    0.00    0.00   28.71   70.30     0  stress
06:03:22 PM  1000      2903   59.41    0.00    0.00   40.59   59.41     1  stress
06:03:22 PM  1000      2904   69.31    0.00    0.00   31.68   69.31     1  stress

06:03:22 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
06:03:23 PM  1000      2902   72.00    0.00    0.00   29.00   72.00     1  stress
06:03:23 PM  1000      2903   61.00    0.00    0.00   38.00   61.00     0  stress
06:03:23 PM  1000      2904   64.00    0.00    0.00   34.00   64.00     1  stress

06:03:23 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
06:03:24 PM  1000      2727    0.00    1.00    0.00    0.00    1.00     0  sshd
06:03:24 PM  1000      2902   55.00    0.00    0.00   45.00   55.00     1  stress
06:03:24 PM  1000      2903   79.00    0.00    0.00   21.00   79.00     0  stress
06:03:24 PM  1000      2904   65.00    0.00    0.00   36.00   65.00     1  stress
06:03:24 PM  1000      2911    0.00    1.00    0.00    1.00    1.00     0  pidstat


上图显示共有3个进程占用了 cpu,由于 cpu 只有2个,任一时刻最多只有2个进程处于 running 状态,其余可运行进程需要等待 cpu,因此 %wait 不为0。

存在 I/O 密集型进程

上图可知,系统负载超过6, 2个 cpu 的 us 使用率极低,sy 使用率不高,但是 iowait(wa)很高。
只有一个进程 stress-ng-hdd 占用了最高的 cpu,但也只有 23.6%

$ mpstat -P ALL 1
Linux 4.15.0-112-generic (aaa_ubuntu)   08/15/2020      _x86_64_        (2 CPU)

07:02:52 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
07:02:53 PM  all    0.00    0.00   19.05   76.19    0.00    4.76    0.00    0.00    0.00    0.00
07:02:53 PM    0    1.11    0.00    7.78   84.44    0.00    6.67    0.00    0.00    0.00    0.00
07:02:53 PM    1    0.00    0.00   30.86   64.20    0.00    3.70    0.00    0.00    0.00    1.23

07:02:53 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
07:02:54 PM  all    0.56    0.00   13.41   82.68    0.00    2.79    0.00    0.00    0.00    0.56
07:02:54 PM    0    0.00    0.00   17.71   82.29    0.00    0.00    0.00    0.00    0.00    0.00
07:02:54 PM    1    0.00    0.00    8.64   85.19    0.00    6.17    0.00    0.00    0.00    0.00

07:02:54 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
07:02:55 PM  all    0.00    0.00   16.48   72.16    0.00    1.70    0.00    0.00    0.00    9.66
07:02:55 PM    0    1.05    0.00   26.32   72.63    0.00    0.00    0.00    0.00    0.00    0.00
07:02:55 PM    1    0.00    0.00    3.75   72.50    0.00    2.50    0.00    0.00    0.00   21.25

上图证实大部分时候,cpu 处于 iowait 状态。
iowait:当系统出现大量 I/O 请求时, cpu(s) 处于空闲状态的占比
换言之,iowait 导致的系统负载升高,说明存在 I/O 密集型进程

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  1      0 1649524  98996 2143636    0    0    62 22164  204  395 14  3 74  9  0
 1  3      0 2177632  98996 1615300    0    0     0 346208  847 1510  0 33 25 42  0
 1  3      0 1981540  98996 1811240    0    0     0 452688  652 2349  0 20  7 73  0
 1  1      0 1763932  98996 2029080    0    0     0 249856  737 3307  1  9 16 75  0
 1  2      0 1834548  98996 1958472    0    0     0 305152  853  800  0 27 13 60  0
 1  2      0 1981648  98996 1811244    0    0     0 424104 1469 2600  1 25  5 69  0
 1  1      0 1820168  98996 1972576    0    0     0 319488 1023 4004  0 10  7 84  0

上图中的 bo列表示每秒发送到块设备的块数。这里 bo 的数值很高,说明系统在不停对设备进行写入操作。

iowait 的一个误区:认为 iowait 高就代表系统有问题。
实际上,iowait 高,只不过是表示系统有大量 I/O,但是 cpu 相当空闲。

以下在相同的 I/O 压力下,加入了 cpu 密集型进程后,可以使得 iowait 归 0。

上图可知,系统负载超高,2个 cpu 占满,但 iowait (wa) 为0.

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 7  4      0 2600296 100532 1190628    0    0    57 32733  310  618 15  5 69 11  0
 6  5      0 2280636 100540 1510400    0    0     0 297180 7457 13156 64 37  0  0  0
 8  0      0 1979456 100540 1811496    0    0     0 308292 8827 16074 63 37  0  0  0
 6  5      0 2487384 100540 1303244    0    0     0  4136 6161 18759 75 26  0  0  0
 6  1      0 2831760 100540 959420    0    0     0 200224 5428 11782 67 33  0  0  0
 7  0      0 2493116 100544 1297968    0    0     0 348316 4865 8087 68 33  0  0  0
 6  1      0 2129112 100556 1662036    0    0     0 336748 4807 7636 67 33  0  0  0
 6  5      0 1979488 100564 1811568    0    0     0 166660 6162 14022 65 35  0  0  0
10  0      0 2951312 100564 839928    0    0     0 81340 5637 15043 67 34  0  0  0
10  0      0 2653460 100592 1137528    0    0     0 288684 6314 11247 69 31  0  0  0
 7  1      0 2336184 100600 1454700    0    0     0 333828 3902 6083 71 30  0  0  0


上图可知,bo 列值很高,证明仍然在进行大量的写设备操作,us列值很高,证明有程序使用了大量 cpu。
在高频 I/O 时间段内,cpu 并不空闲,因此 iowait 为0

存在大量处于可运行状态的进程
特征:running 队列过长(或R状态进程过多),CPU使用率高,但每个进程的CPU使用率不高

上图可见系统负载 > 9,2个 cpu 占满,11个 running 进程,其中10个进程占用 cpu 的总和接近了 2个 cpu。

$ pidstat -u 1
Linux 4.15.0-112-generic (aaa_ubuntu)   08/15/2020      _x86_64_        (2 CPU)

06:22:17 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
06:22:18 PM  1000      2547   18.27    0.00    0.00   75.00   18.27     1  stress
06:22:18 PM  1000      2548   19.23    0.00    0.00   75.96   19.23     0  stress
06:22:18 PM  1000      2549   20.19    0.00    0.00   78.85   20.19     1  stress
06:22:18 PM  1000      2550   19.23    0.00    0.00   76.92   19.23     1  stress
06:22:18 PM  1000      2551   19.23    0.00    0.00   76.92   19.23     1  stress
06:22:18 PM  1000      2552   19.23    0.00    0.00   76.92   19.23     0  stress
06:22:18 PM  1000      2553   19.23    0.00    0.00   76.92   19.23     0  stress
06:22:18 PM  1000      2554   19.23    0.00    0.00   77.88   19.23     0  stress
06:22:18 PM  1000      2555   19.23    0.00    0.00   77.88   19.23     0  stress
06:22:18 PM  1000      2556   19.23    0.00    0.00   76.92   19.23     1  stress

06:22:18 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
06:22:19 PM  1000      2547   21.00    0.00    0.00   82.00   21.00     1  stress
06:22:19 PM  1000      2548   20.00    0.00    0.00   80.00   20.00     0  stress
06:22:19 PM  1000      2549   19.00    0.00    0.00   80.00   19.00     1  stress
06:22:19 PM  1000      2550   20.00    0.00    0.00   80.00   20.00     1  stress
06:22:19 PM  1000      2551   20.00    0.00    0.00   80.00   20.00     1  stress
06:22:19 PM  1000      2552   20.00    0.00    0.00   81.00   20.00     0  stress
06:22:19 PM  1000      2553   19.00    0.00    0.00   80.00   19.00     0  stress
06:22:19 PM  1000      2554   20.00    0.00    0.00   79.00   20.00     0  stress
06:22:19 PM  1000      2555   20.00    0.00    0.00   80.00   20.00     0  stress
06:22:19 PM  1000      2556   20.00    0.00    0.00   80.00   20.00     1  stress
06:22:19 PM  1000      2609    0.00    1.00    0.00    0.00    1.00     1  pidstat


%wait 高,表示进程等待CPU的时间长。(注意,pidstat 中的 %wait 跟 top命令中的 wait 不一样,top的 wait 指的是 iowait)
由此可知,这些进程大部分时候都在等待 cpu。

存在大量处于可运行状态的线程
当系统存在大量可运行线程时,就算可运行进程很少,也会造成 system load 升高。

上图可看出 load average 很高,当前只有一个进程处于 running 状态,cpu sy 比 cpu us 要高,这个 sysbench 的进程占用了最多的 cpu。

$ pidstat -u 1 -p 2806
Linux 4.15.0-112-generic (aaa_ubuntu)   08/15/2020      _x86_64_        (2 CPU)

05:16:32 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
05:16:33 PM  1000      2806   60.00  100.00    0.00    0.00  100.00     0  sysbench
05:16:34 PM  1000      2806   61.00  100.00    0.00    0.00  100.00     0  sysbench
05:16:35 PM  1000      2806   54.00  100.00    0.00    0.00  100.00     0  sysbench
05:16:36 PM  1000      2806   56.00  100.00    0.00    0.00  100.00     0  sysbench
05:16:37 PM  1000      2806   58.00  100.00    0.00    0.00  100.00     0  sysbench
05:16:38 PM  1000      2806   69.00  100.00    0.00    0.00  100.00     0  sysbench

上图每秒打印一次 sysbench 进程的 cpu 使用率,可看出确实占用了大量 cpu。

$ pidstat -ut 1 -p 2806
Linux 4.15.0-112-generic (aaa_ubuntu)   08/15/2020      _x86_64_        (2 CPU)

05:17:04 PM   UID      TGID       TID    %usr %system  %guest   %wait    %CPU   CPU  Command
05:17:05 PM  1000      2806         -   64.00  100.00    0.00    0.00  100.00     0  sysbench
05:17:05 PM  1000         -      2806    0.00    0.00    0.00    0.00    0.00     0  |__sysbench
05:17:05 PM  1000         -      2807    8.00   14.00    0.00   49.00   22.00     1  |__sysbench
05:17:05 PM  1000         -      2808    3.00   19.00    0.00   51.00   22.00     1  |__sysbench
05:17:05 PM  1000         -      2809    7.00    9.00    0.00   64.00   16.00     0  |__sysbench
05:17:05 PM  1000         -      2810    9.00    8.00    0.00   63.00   17.00     0  |__sysbench
05:17:05 PM  1000         -      2811    6.00   11.00    0.00   68.00   17.00     1  |__sysbench
05:17:05 PM  1000         -      2812    8.00   16.00    0.00   42.00   24.00     1  |__sysbench
05:17:05 PM  1000         -      2813    8.00   10.00    0.00   63.00   18.00     0  |__sysbench
05:17:05 PM  1000         -      2814    3.00   20.00    0.00   56.00   23.00     1  |__sysbench
05:17:05 PM  1000         -      2815    5.00   11.00    0.00   67.00   16.00     0  |__sysbench
05:17:05 PM  1000         -      2816    8.00   10.00    0.00   65.00   18.00     0  |__sysbench

05:17:05 PM   UID      TGID       TID    %usr %system  %guest   %wait    %CPU   CPU  Command
05:17:06 PM  1000      2806         -   58.00  100.00    0.00    0.00  100.00     0  sysbench
05:17:06 PM  1000         -      2806    0.00    0.00    0.00    0.00    0.00     0  |__sysbench
05:17:06 PM  1000         -      2807    6.00   12.00    0.00   57.00   18.00     1  |__sysbench
05:17:06 PM  1000         -      2808    4.00   15.00    0.00   61.00   19.00     1  |__sysbench
05:17:06 PM  1000         -      2809    6.00   14.00    0.00   53.00   20.00     0  |__sysbench
05:17:06 PM  1000         -      2810    6.00   14.00    0.00   60.00   20.00     0  |__sysbench
05:17:06 PM  1000         -      2811    6.00   13.00    0.00   65.00   19.00     1  |__sysbench
05:17:06 PM  1000         -      2812    4.00   14.00    0.00   58.00   18.00     1  |__sysbench
05:17:06 PM  1000         -      2813    5.00   14.00    0.00   57.00   19.00     0  |__sysbench
05:17:06 PM  1000         -      2814    6.00   13.00    0.00   66.00   19.00     1  |__sysbench
05:17:06 PM  1000         -      2815    6.00   15.00    0.00   63.00   21.00     0  |__sysbench
05:17:06 PM  1000         -      2816    9.00   11.00    0.00   55.00   20.00     0  |__sysbench


上图加上 -t 选项后,打印了 sysbench 内部线程的 cpu 使用率,可以看出 %wait 很高,这代表各个线程等待 cpu 的时间很长。

查看线程上下文切换

上图可知存在大量可运行的线程导致系统负载升高

$ mpstat -P ALL 1
Linux 4.15.0-112-generic (aaa_ubuntu)   08/15/2020      _x86_64_        (2 CPU)

06:42:13 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
06:42:14 PM  all   36.00    0.00   64.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:42:14 PM    0   31.68    0.00   68.32    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:42:14 PM    1   40.00    0.00   60.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00

06:42:14 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
06:42:15 PM  all   34.00    0.00   66.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:42:15 PM    0   32.00    0.00   68.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:42:15 PM    1   36.00    0.00   64.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00

06:42:15 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
06:42:16 PM  all   30.50    0.00   69.50    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:42:16 PM    0   31.00    0.00   69.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:42:16 PM    1   30.00    0.00   70.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00


上图可知,大部分 cpu 用于 kernel (%sys 比 %usr 高很多)

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 8  0      0 3266356  96552 536796    0    0    36   393 3394 3068 38 13 47  1  0
 7  0      0 3266376  96552 536796    0    0     0     0 39782 943369 33 67  1  0  0
 8  0      0 3266376  96552 536796    0    0     0     0 38650 909726 30 70  0  0  0
10  0      0 3266376  96552 536796    0    0     0     0 38048 971882 31 69  0  0  0
 7  0      0 3266376  96552 536796    0    0     0     0 39544 962102 30 70  0  0  0
 8  0      0 3266376  96552 536796    0    0     0     0 39163 917229 28 72  0  0  0
 8  0      0 3266376  96552 536796    0    0     0     0 39437 1003420 30 70  0  0  0
10  0      0 3266376  96552 536796    0    0     0     0 42390 939651 27 73  0  0  0
 8  0      0 3266376  96552 536796    0    0     0     0 43100 977931 34 66  0  0  0
 9  0      0 3266376  96552 536796    0    0     0     0 40550 971362 36 64  0  0  0
 6  0      0 3266376  96552 536796    0    0     0     0 39410 947462 29 71  0  0  0
 8  0      0 3266376  96552 536796    0    0     0     0 40276 944977 28 72  0  0  0

上图可知,上下文切换次数超高(cs 对应列), 中断数也很高(in 对应列)

$ pidstat -wt 1 -p 2938
Linux 4.15.0-112-generic (aaa_ubuntu)   08/15/2020      _x86_64_        (2 CPU)

05:17:44 PM   UID      TGID       TID   cswch/s nvcswch/s  Command
05:17:45 PM  1000      2938         -      0.00      0.00  sysbench
05:17:45 PM  1000         -      2806      0.00      0.00  |__sysbench
05:17:45 PM  1000         -      2807  10785.00  77586.00  |__sysbench
05:17:45 PM  1000         -      2808   8773.00  72765.00  |__sysbench
05:17:45 PM  1000         -      2809  10349.00  82741.00  |__sysbench
05:17:45 PM  1000         -      2810   9048.00  77654.00  |__sysbench
05:17:45 PM  1000         -      2811  11500.00  81969.00  |__sysbench
05:17:45 PM  1000         -      2812  10458.00  81610.00  |__sysbench
05:17:45 PM  1000         -      2813   6844.00  85061.00  |__sysbench
05:17:45 PM  1000         -      2814  11279.00  82209.00  |__sysbench
05:17:45 PM  1000         -      2815  11345.00  75471.00  |__sysbench
05:17:45 PM  1000         -      2816   9282.00  82881.00  |__sysbench

05:17:45 PM   UID      TGID       TID   cswch/s nvcswch/s  Command
05:17:46 PM  1000      2938         -      0.00      0.00  sysbench
05:17:46 PM  1000         -      2806      0.00      0.00  |__sysbench
05:17:46 PM  1000         -      2807   8328.00  82343.00  |__sysbench
05:17:46 PM  1000         -      2808   7356.00  84236.00  |__sysbench
05:17:46 PM  1000         -      2809   8468.00  77616.00  |__sysbench
05:17:46 PM  1000         -      2810  10228.00  82942.00  |__sysbench
05:17:46 PM  1000         -      2811  10503.00  82221.00  |__sysbench
05:17:46 PM  1000         -      2812  12488.00  75746.00  |__sysbench
05:17:46 PM  1000         -      2813  10551.00  84009.00  |__sysbench
05:17:46 PM  1000         -      2814  11311.00  81515.00  |__sysbench
05:17:46 PM  1000         -      2815   6739.00  74858.00  |__sysbench
05:17:46 PM  1000         -      2816   9154.00  84515.00  |__sysbench


上图打印的是 sysbench 进程内线程的上下文切换情况。
cswch:自愿上下文切换次数,当所需资源不可用时就会出现。
nvcswch:非自愿上下文切换次数,当任务所分派的 cpu 时间分片用完后,就会被要求强制放弃 cpu。(或者被更高优先级的抢占)
上图显示 nvcwsch 很大,说明同一时间,系统存在大量可运行的线程,但是 cpu 不足,导致频繁切换线程上下文。线程上下文切换也是需要消耗系统 cpu 的,所以 cpu sy 很高。

之前通过 vmstat 查看到中断数也很高,可以通过命令 watch -d cat /proc/interrupts 来确定是哪种硬中断导致。
上图可知,RES 重调度中断增长很快,RES 中断用于不停唤醒空闲 CPU 来处理任务(只在多 CPU 系统才存在),说明了上下文频繁切换(这里是线程上下文)。

查看短进程导致CPU升高

上图可知,cpu 使用率颇高,但是 top 列表中没有出现高 cpu 的进程。

$ mpstat -P ALL 1
Linux 4.15.0-112-generic (aaa_ubuntu)   08/16/2020      _x86_64_        (2 CPU)

04:35:37 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
04:35:38 PM  all   19.10    0.00    0.50    5.03    0.00    0.50    0.00    0.00    0.00   74.87
04:35:38 PM    0   36.63    0.00    0.00    2.97    0.00    0.99    0.00    0.00    0.00   59.41
04:35:38 PM    1    2.04    0.00    1.02    6.12    0.00    0.00    0.00    0.00    0.00   90.82

04:35:38 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
04:35:39 PM  all   34.18    0.00    1.02    4.08    0.00    0.00    0.00    0.00    0.00   60.71
04:35:39 PM    0   22.45    0.00    1.02    4.08    0.00    1.02    0.00    0.00    0.00   71.43
04:35:39 PM    1   45.36    0.00    1.03    4.12    0.00    0.00    0.00    0.00    0.00   49.48

04:35:39 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
04:35:40 PM  all   50.75    0.00    1.51    2.51    0.00    0.50    0.00    0.00    0.00   44.72
04:35:40 PM    0   10.20    0.00    1.02    5.10    0.00    0.00    0.00    0.00    0.00   83.67
04:35:40 PM    1   91.00    0.00    1.00    0.00    0.00    1.00    0.00    0.00    0.00    7.00

04:35:40 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
04:35:41 PM  all   51.53    0.00    1.02    3.57    0.00    0.00    0.00    0.00    0.00   43.88
04:35:41 PM    0   62.63    0.00    2.02    1.01    0.00    0.00    0.00    0.00    0.00   34.34
04:35:41 PM    1   40.00    0.00    1.00    6.00    0.00    0.00    0.00    0.00    0.00   53.00

04:35:41 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
04:35:42 PM  all   51.01    0.00    1.52    3.03    0.00    0.00    0.00    0.00    0.00   44.44
04:35:42 PM    0   67.33    0.00    1.98    1.98    0.00    0.00    0.00    0.00    0.00   28.71
04:35:42 PM    1   34.38    0.00    1.04    4.17    0.00    0.00    0.00    0.00    0.00   60.42

上图可知,2个 cpu 大部分时间确实是花费在用户态程序的执行上。

$ pidstat -u 1
Linux 4.15.0-112-generic (aaa_ubuntu)   08/16/2020      _x86_64_        (2 CPU)

04:38:20 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
04:38:21 PM     0       217    0.00    1.00    0.00    0.00    1.00     0  kworker/0:1H
04:38:21 PM     0       337    0.00    1.00    0.00    0.00    1.00     0  jbd2/sda2-8
04:38:21 PM     0       819    5.00    1.00    0.00    0.00    6.00     0  snapd
04:38:21 PM  1000      3821    1.00    0.00    0.00    0.00    1.00     0  pidstat
04:38:21 PM     0      3825    2.00    0.00    0.00    0.00    2.00     0  stress

04:38:21 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
04:38:22 PM     0       819    5.94    0.00    0.00    0.00    5.94     0  snapd
04:38:22 PM     0      1951    0.00    0.99    0.00    0.00    0.99     0  kworker/u4:0
04:38:22 PM     0      3829    1.98    0.00    0.00    0.00    1.98     0  stress

04:38:22 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
04:38:23 PM     0       819    7.00    0.00    0.00    0.00    7.00     0  snapd
04:38:23 PM  1000      2446    0.00    1.00    0.00    0.00    1.00     0  sshd

04:38:23 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
04:38:24 PM     0         8    0.00    1.00    0.00    0.00    1.00     0  rcu_sched
04:38:24 PM     0       215    0.00    1.00    0.00    0.00    1.00     1  kworker/1:1H
04:38:24 PM     0       819    5.00    1.00    0.00    0.00    6.00     0  snapd
04:38:24 PM     0      3833    2.00    0.00    0.00    0.00    2.00     1  stress

04:38:24 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
04:38:25 PM     0       819    6.00    0.00    0.00    0.00    6.00     0  snapd
04:38:25 PM  1000      2446    0.00    1.00    0.00    0.00    1.00     0  sshd
04:38:25 PM  1000      3821    0.00    1.00    0.00    1.00    1.00     0  pidstat
04:38:25 PM     0      3837    1.00    0.00    0.00    0.00    1.00     0  stress

04:38:25 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
04:38:26 PM     0       337    0.00    1.00    0.00    1.00    1.00     1  jbd2/sda2-8
04:38:26 PM     0       819    6.00    1.00    0.00    0.00    7.00     0  snapd
04:38:26 PM     0      3841    1.00    0.00    0.00    0.00    1.00     1  stress


上图没有发现使用大量 cpu 的进程。

这时候就需要怀疑一下是不是短进程在作怪。可以使用以下工具来查看。
这个脚本可以直接使用,不需要其他依赖或者安装。
perf-tools/execsnoop

# ./execsnoop -t
Tracing exec()s. Ctrl-C to end.
Instrumenting sys_execve
TIMEs               PID   PPID ARGS
2770.354823        7359   7355 gawk -v o=1 -v opt_name=0 -v name= -v opt_duration=0 [...]
2770.356679        7360   7358 cat -v trace_pipe
2771.141217        7362   7361   new_child_proc-7362  [001] ....  2771.141217: execsnoop_sys_execve: (SyS_execve+0x0/0x40)
2771.142194        7363   7362 /usr/bin/stress -c 1 -t 1
2772.141682        7366   7365   new_child_proc-7366  [001] ....  2772.141682: execsnoop_sys_execve: (SyS_execve+0x0/0x40)
2772.142493        7367   7366 /usr/bin/stress -c 1 -t 1
2773.143181        7370   7369   new_child_proc-7370  [001] ....  2773.143181: execsnoop_sys_execve: (SyS_execve+0x0/0x40)
2773.144564        7371   7370 /usr/bin/stress -c 1 -t 1
2774.143527        7374   7373   new_child_proc-7374  [001] ....  2774.143527: execsnoop_sys_execve: (SyS_execve+0x0/0x40)
2774.144244        7375   7374 /usr/bin/stress -c 1 -t 1
2775.143685        7378   7377   new_child_proc-7378  [000] ....  2775.143685: execsnoop_sys_execve: (SyS_execve+0x0/0x40)
2775.144391        7379   7378 /usr/bin/stress -c 1 -t 1
2777.147780        7382   7381   new_child_proc-7382  [001] ....  2777.147780: execsnoop_sys_execve: (SyS_execve+0x0/0x40)
2777.148508        7383   7382 /usr/bin/stress -c 1 -t 1
2778.148406        7386   7385   new_child_proc-7386  [001] ....  2778.148406: execsnoop_sys_execve: (SyS_execve+0x0/0x40)
2778.149217        7387   7386 /usr/bin/stress -c 1 -t 1
2779.148549        7390   7389   new_child_proc-7390  [001] ....  2779.148549: execsnoop_sys_execve: (SyS_execve+0x0/0x40)
2779.149486        7391   7390 /usr/bin/stress -c 1 -t 1

上图可知,大约每隔1s,就会产生一个新的进程,这个进程又调用了 system 方法来产生另外一个子进程
"/usr/bin/stress -c 1 -t 1"

$ ps aux | grep 7355
root      8210  0.0  0.0  13136  1028 pts/1    S+   16:57   0:00 grep --color=auto 7355
$ ps aux | grep 7359
root      8224  0.0  0.0  13136  1008 pts/1    S+   16:57   0:00 grep --color=auto 7359

但如果使用 ps 来查找这些进程的话,又会发现它们都不存在。很明显,这些都是短时进程。
但是,从上图可以看到这些短进程,都包含 new_child_proc 。
上图通过 watch -d “pstree -p | grep new_child_proc” 可以看到这些短时进程,都是由父进程 pid=2502 产生的。

$ ps aux | grep 2502
root      2502  0.0  0.0   4376  1108 pts/0    S+   16:32   0:00 ./new_child_proc
root     10527  0.0  0.0  13136  1060 pts/1    S+   17:05   0:00 grep --color=auto 2502

上图可以确定这个进程确实存在。kill 了它后就正常了。

查看僵尸进程

上图可知,当前系统存在大量僵尸进程。

$ ps aux | grep Z+
root     10962  0.0  0.0      0     0 pts/0    Z+   17:17   0:00 [new_zombie_proc] <defunct>
root     10965  0.0  0.0      0     0 pts/0    Z+   17:17   0:00 [new_zombie_proc] <defunct>
root     10966  0.0  0.0      0     0 pts/0    Z+   17:17   0:00 [new_zombie_proc] <defunct>
root     10967  0.0  0.0      0     0 pts/0    Z+   17:17   0:00 [new_zombie_proc] <defunct>
root     10968  0.0  0.0      0     0 pts/0    Z+   17:17   0:00 [new_zombie_proc] <defunct>
root     10969  0.0  0.0      0     0 pts/0    Z+   17:17   0:00 [new_zombie_proc] <defunct>
...

$ ps aux | grep Z+ | wc -l
685

Z+ 表示僵尸进程。
上图可知,僵尸进程数量很多。

$ pstree -p | grep new_zombie_proc | head -n 10
           |-sshd(942)-+-sshd(1979)---sshd(2180)---bash(2182)---sudo(2241)---bash(2243)---new_zombie_proc(10961)-+-new_zombie_proc(+
           |           |                                                                                         |-new_zombie_proc(+
           |           |                                                                                         |-new_zombie_proc(+
           |           |                                                                                         |-new_zombie_proc(+
           |           |                                                                                         |-new_zombie_proc(+
           |           |                                                                                         |-new_zombie_proc(+
           |           |                                                                                         |-new_zombie_proc(+
           |           |                                                                                         |-new_zombie_proc(+
           |           |                                                                                         |-new_zombie_proc(+
           |           |                                                                                         |-new_zombie_proc(+

上图可以看到僵尸进程的父进程为 pid=10961。

# strace -p 10961
strace: Process 10961 attached
restart_syscall(<... resuming interrupted nanosleep ...>) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f851507d790) = 12020
nanosleep({tv_sec=1, tv_nsec=0}, {tv_sec=0, tv_nsec=999992096}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12020, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
restart_syscall(<... resuming interrupted nanosleep ...>) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f851507d790) = 12021
nanosleep({tv_sec=1, tv_nsec=0}, {tv_sec=0, tv_nsec=999992340}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12021, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
restart_syscall(<... resuming interrupted nanosleep ...>) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f851507d790) = 12022
nanosleep({tv_sec=1, tv_nsec=0}, {tv_sec=0, tv_nsec=999957790}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12022, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
restart_syscall(<... resuming interrupted nanosleep ...>^Cstrace: Process 10961 detached
 <detached ...>

上图使用 strace 可以探查到 pid=10961 的进程使用的 syscall。

# strace -c -p 10961
strace: Process 10961 attached
^Cstrace: Process 10961 detached
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 81.59    0.000195          49         4           clone
 13.39    0.000032           8         4           restart_syscall
  5.02    0.000012           3         4         4 nanosleep
------ ----------- ----------- --------- --------- ----------------
100.00    0.000239                    12         4 total


这里显示的是一段时间内 syscall 的统计。kill 掉 pid=10961 的进程后,所有僵尸进程都消失了。
产生僵尸进程是因为子进程退出后,父进程没有调用 wait(…),导致子进程的信息还一直残留。当父进程被 kill 后,这些子进程会被当成孤立进程,然后挂接到 init 进程下,由 init 进程进行收割。
————————————————
版权声明:本文为CSDN博主「懒惰的劳模」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/helowken2/article/details/107478974

 

posted @ 2022-01-19 00:16  Sky&Zhang  阅读(181)  评论(0编辑  收藏  举报