利用 pidstat 分析进程的资源占用情况
Jun 26, 2020 23:00 · 1797 words · 4 minute read
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 严重过载了。