利用 pidstat 分析进程的资源占用情况

Jun 26, 2020 23:00 · 1797 words · 4 minute read Linux Kernel

pidstat 是 sysstat 系列工具包含的一个命令,主要用于监控 Linux 内核管理的进程的资源占用情况。

用法

CentOS 的 pidstat 版本有点老会导致缺失 %wait 数据,我们需要手动升级至 11.5.5 以上的版本:

$ git clone https://github.com/sysstat/sysstat.git
$ cd sysstat
$ ./configure
$ make && make install
$ source .bashrc
  • -d 显示 I/O 状况
    • kB_rd/s 读盘速度
    • kB_wr/s 写盘速度
    • kB_ccwr/s 被取消写盘的速度,当存在脏页缓存可能会出现这种情况
  • -u 显示 CPU 使用率
    • %usr 任务在用户态执行的 CPU 利用率
    • %system 任务在内核态执行的 CPU 利用率
    • %guest 任务在虚拟态执行的 CPU 利用率
    • %wait 任务等待 CPU 的几率
    • %CPU 任务总的 CPU 利用率
    • CPU 任务所使用的 CPU 编号
    • Command 任务的完整命令
  • -p ${PID} 指定某个进程
  • -r 显示页面错误和内存使用情况
    • minflt/s 每秒次缺页次数
    • majflt/s 每秒主缺页次数
    • VSZ 虚拟内存使用
    • RSS 栈 + 堆内存使用
  • -w 显示上下文切换

所有进程的 CPU

$ pidstat -u 10 2 # 每次采样时间 10 秒,两次
Linux 3.10.0-1127.8.2.el7.x86_64 (network-test) 	06/26/2020 	_x86_64_	(2 CPU)

08:13:03 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
08:13:13 PM     0      1507    0.00    0.10    0.00    0.00    0.10     1  rsyslogd
08:13:13 PM     0      1549    0.00    0.20    0.00    0.00    0.20     0  containerd
08:13:13 PM    42      2224    0.10    0.00    0.00    0.00    0.10     0  gnome-shell
08:13:13 PM     0     23273    0.00    0.10    0.00    0.00    0.10     0  pidstat

08:13:13 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
08:13:23 PM     0      1507    0.10    0.00    0.00    0.00    0.10     1  rsyslogd
08:13:23 PM     0      1549    0.10    0.10    0.00    0.00    0.20     0  containerd
08:13:23 PM     0     22624    0.00    0.10    0.00    0.00    0.10     0  kworker/0:1

Average:      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
Average:        0      1507    0.05    0.05    0.00    0.00    0.10     -  rsyslogd
Average:        0      1549    0.05    0.15    0.00    0.00    0.20     -  containerd
Average:       42      2224    0.05    0.00    0.00    0.00    0.05     -  gnome-shell
Average:        0     22624    0.00    0.05    0.00    0.00    0.05     -  kworker/0:1
Average:        0     23273    0.00    0.05    0.00    0.00    0.05     -  pidstat

从 pidstat 的输出可以看到 pidstat 自身占用了 0.2% 的 CPU,而且在内核态运行。

我们使用 stress 容器模拟 CPU 密集型场景:

$ docker run --rm \
    -d polinux/stress:latest stress \
        --cpu 1 \
        --timeout 600
  • --cpu 1 将 CPU 吃满
  • --timeout 600 持续 600 秒也就是 10 分钟

使用 pidstat 查看进程的 CPU 资源占用情况:

pidstat -u 5 2
Linux 3.10.0-1127.8.2.el7.x86_64 (network-test) 	06/26/2020 	_x86_64_	(2 CPU)

08:16:59 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
08:17:04 PM     0       850    0.00    0.20    0.00    0.00    0.20     1  ksmtuned
08:17:04 PM     0     23885  100.00    0.00    0.00    0.00  100.00     1  stress
08:17:04 PM     0     24096    0.00    0.20    0.00    0.00    0.20     0  pidstat

08:17:04 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
08:17:09 PM     0       421    0.00    0.20    0.00    0.20    0.20     0  xfsaild/dm-0
08:17:09 PM     0      1549    0.20    0.00    0.00    0.00    0.20     0  containerd
08:17:09 PM     0     23885  100.00    0.00    0.00    0.00  100.00     1  stress
08:17:09 PM     0     24096    0.00    0.20    0.00    0.00    0.20     0  pidstat

Average:      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
Average:        0       421    0.00    0.10    0.00    0.10    0.10     -  xfsaild/dm-0
Average:        0       850    0.00    0.10    0.00    0.00    0.10     -  ksmtuned
Average:        0      1549    0.10    0.00    0.00    0.00    0.10     -  containerd
Average:        0     23885  100.00    0.00    0.00    0.00  100.00     -  stress
Average:        0     24096    0.00    0.20    0.00    0.00    0.20     -  pidstat

stress 进程运行在用户态确实占用了几乎全部 CPU。

接着使用 stress 容器模拟内存占用型场景:

$ docker run --rm \
    -d polinux/stress:latest stress \
        --vm 2 \
        --vm-bytes 1024M \
        --vm-hang 600 \
        --timeout 600
  • --vm 2 开启两个分配内存的进程
  • --vm-bytes 128M 每个工作进程分配 128MB 内存
  • --vm-hang 维持 600 秒后释放内存

使用 pidstat 查看进程的内存资源占用情况:

$ ps -ef | grep stress
root      9904  9887  0 22:34 ?        00:00:00 stress --vm 2 --vm-bytes 1024M --vm-hang 600 --timeout 600
root      9932  9904  1 22:34 ?        00:00:00 stress --vm 2 --vm-bytes 1024M --vm-hang 600 --timeout 600
root      9933  9904  1 22:34 ?        00:00:00 stress --vm 2 --vm-bytes 1024M --vm-hang 600 --timeout 600
$ pidstat -p 9932 -r 5 2
Linux 3.10.0-1127.8.2.el7.x86_64 (network-test) 	06/26/2020 	_x86_64_	(2 CPU)

10:34:46 PM   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
10:34:51 PM     0      9932      0.00      0.00 1049344 1048660  27.06  stress
10:34:56 PM     0      9932      0.00      0.00 1049344 1048660  27.06  stress
Average:        0      9932      0.00      0.00 1049344 1048660  27.06  stress
$ pidstat -p 9933 -r 5 2
Linux 3.10.0-1127.8.2.el7.x86_64 (network-test) 	06/26/2020 	_x86_64_	(2 CPU)

10:35:12 PM   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
10:35:17 PM     0      9933      0.00      0.00 1049344 1048460  27.05  stress
10:35:22 PM     0      9933      0.00      0.00 1049344 1048460  27.05  stress
Average:        0      9933      0.00      0.00 1049344 1048460  27.05  stress

实际上 9932 和 9933 是 9904 fork 出的子进程,所以它们的父进程 PID 都为 9904,RSS 这一栏的数据与我们启动 stress 容器时设置的 1GB 内存相差无几。

然后使用 stress 容器来模拟 IO 密集型场景:

$ docker run --rm \
    -d polinux/stress:latest stress \
        --io 1 \
        --hdd 1 \
        --timeout 600
  • --io 1 不停执行 sync
  • --hdd 1 写盘

使用 pidstat 查看进程的 I/O 资源占用情况:

$ pidstat -d 5 2
Linux 3.10.0-1127.8.2.el7.x86_64 (network-test) 	06/26/2020 	_x86_64_	(2 CPU)

10:49:03 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
10:49:08 PM     0      5851      0.00      0.00      0.00     206  kworker/u64:0
10:49:08 PM     0     12761      0.00      0.00  82730.98      88  stress
10:49:08 PM     0     12762      0.00 2000861.96 290738.82      44  stress

10:49:08 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
10:49:13 PM     0      5851      0.00      0.00      0.00      29  kworker/u64:0
10:49:13 PM     0     12761      0.00      0.00    509.60      66  stress
10:49:13 PM     0     12762      0.00 2532544.80      4.80       1  stress

Average:      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
Average:        0      5851      0.00      0.00      0.00     118  kworker/u64:0
Average:        0     12761      0.00      0.00  42027.33      77  stress
Average:        0     12762      0.00 2264071.29 146811.09      22  stress

正如预期的那样 stress 进程正在疯狂写盘。

最后还是使用 stress 容器来模拟 CPU 竞争:

$ docker run --rm \
    -d polinux/stress:latest stress \
        --cpu 8 \
        --timeout 600
$ pidstat -u 5 2
Linux 3.10.0-1127.8.2.el7.x86_64 (network-test) 	06/26/2020 	_x86_64_	(2 CPU)

10:59:58 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
11:00:03 PM    81       723    0.20    0.00    0.00    0.59    0.20     0  dbus-daemon
11:00:03 PM     0       823    0.00    0.20    0.00    0.20    0.20     0  systemd-logind
11:00:03 PM   998       830    0.59    0.40    0.00    1.19    0.99     0  polkitd
11:00:03 PM     0      1498    0.00    0.20    0.00    0.00    0.20     1  cupsd
11:00:03 PM     0      1549    0.20    0.00    0.00    0.00    0.20     0  containerd
11:00:03 PM    42      2224    0.20    0.20    0.00    0.20    0.40     0  gnome-shell
11:00:03 PM     0     15218   26.34    0.00    0.00   73.27   26.34     1  stress
11:00:03 PM     0     15219   23.96    0.00    0.00   75.05   23.96     0  stress
11:00:03 PM     0     15220   24.75    0.00    0.00   74.85   24.75     1  stress
11:00:03 PM     0     15221   23.96    0.00    0.00   74.85   23.96     0  stress
11:00:03 PM     0     15222   24.16    0.00    0.00   75.25   24.16     1  stress
11:00:03 PM     0     15223   24.16    0.00    0.00   75.05   24.16     1  stress
11:00:03 PM     0     15224   23.96    0.00    0.00   75.45   23.96     0  stress
11:00:03 PM     0     15225   23.96    0.00    0.00   75.45   23.96     0  stress
11:00:03 PM     0     15258    0.00    0.40    0.00    0.00    0.40     0  pidstat

11:00:03 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
11:00:08 PM     0      1549    0.00    0.20    0.00    0.00    0.20     0  containerd
11:00:08 PM     0     15218   26.40    0.00    0.00   73.20   26.40     1  stress
11:00:08 PM     0     15219   24.00    0.00    0.00   76.60   24.00     1  stress
11:00:08 PM     0     15220   25.20    0.00    0.00   74.60   25.20     1  stress
11:00:08 PM     0     15221   24.00    0.00    0.00   75.60   24.00     0  stress
11:00:08 PM     0     15222   25.40    0.00    0.00   74.20   25.40     0  stress
11:00:08 PM     0     15223   24.20    0.00    0.00   76.00   24.20     1  stress
11:00:08 PM     0     15224   24.60    0.00    0.00   75.40   24.60     0  stress
11:00:08 PM     0     15225   24.60    0.00    0.00   74.60   24.60     0  stress
11:00:08 PM     0     15258    0.00    0.20    0.00    0.00    0.20     0  pidstat

Average:      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
Average:       81       723    0.10    0.00    0.00    0.30    0.10     -  dbus-daemon
Average:        0       823    0.00    0.10    0.00    0.10    0.10     -  systemd-logind
Average:      998       830    0.30    0.20    0.00    0.60    0.50     -  polkitd
Average:        0      1498    0.00    0.10    0.00    0.10    0.10     -  cupsd
Average:        0      1549    0.10    0.10    0.00    0.00    0.20     -  containerd
Average:       42      2224    0.10    0.10    0.00    0.10    0.20     -  gnome-shell
Average:        0     15218   26.37    0.00    0.00   73.23   26.37     -  stress
Average:        0     15219   23.98    0.00    0.00   75.82   23.98     -  stress
Average:        0     15220   24.98    0.00    0.00   74.73   24.98     -  stress
Average:        0     15221   23.98    0.00    0.00   75.22   23.98     -  stress
Average:        0     15222   24.78    0.00    0.00   74.73   24.78     -  stress
Average:        0     15223   24.18    0.00    0.00   75.52   24.18     -  stress
Average:        0     15224   24.28    0.00    0.00   75.42   24.28     -  stress
Average:        0     15225   24.28    0.00    0.00   75.02   24.28     -  stress
Average:        0     15258    0.00    0.30    0.00    0.00    0.30     -  pidstat

8 个进程正在争抢两个 CPU,每个进程等待 CPU 的时间高达 75%,这已经导致 CPU 严重过载了。