对于 CPU 使用率,top 默认 3 秒时间间隔;ps 使用的是进程的整个生命周期。
top 显示系统总体的 CPU 和内存使用情况,及各个进程的资源使用情况;ps 只显示每隔进程的资源使用情况。
# 默认每 3 秒刷新一次
~$ top
top - 14:05:40 up 23 min, 1 user, load average: 1.41, 1.14, 1.11
Tasks: 176 total, 2 running, 173 sleeping, 0 stopped, 1 zombie
%Cpu(s): 1.9 us, 2.7 sy, 27.8 ni, 67.4 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1789476 total, 111148 free, 651556 used, 1026772 buff/cache
KiB Swap: 1533948 total, 1533948 free, 0 used. 910880 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2952 root 39 19 163068 99540 60920 R 99.3 5.6 20:28.26 unattended+
3690 yjp 20 0 1245468 86996 53372 S 2.7 4.9 0:12.35 compiz
1399 root 20 0 531504 117032 40780 S 2.0 6.5 0:09.61 Xorg
4311 yjp 20 0 663668 35680 28568 S 1.0 2.0 0:00.72 gnome-term+
第三行为系统的 CPU 使用率。
top 默认显示所有 CPU 的平均值,可按下数字 1,切换到每隔 CPU 的使用率。
# 每 1 秒输出一组数据,共输出 5 组
$ pidstat 1 5
Linux 4.13.0-45-generic (yjp-VirtualBox) 2019年04月27日 _x86_64_ (2 CPU)
14时24分19秒 UID PID %usr %system %guest %CPU CPU Command
14时24分20秒 0 1399 2.00 0.00 0.00 2.00 0 Xorg
14时24分20秒 0 1846 0.00 1.00 0.00 1.00 0 dockerd
14时24分20秒 0 2043 1.00 1.00 0.00 2.00 1 docker-containe
...
Average: UID PID %usr %system %guest %CPU CPU Command
Average: 0 8 0.00 0.20 0.00 0.20 - rcu_sched
Average: 0 1399 2.00 0.80 0.00 2.79 - Xorg
Average: 0 1480 0.20 0.00 0.00 0.20 - ovs-vswitchd
...
最后会计算 5 组数据的平均值。
perf top
perf top 可实时显示占用 CPU 时钟最多的函数或指令,因此可用来查找热点函数。
$ perf top
Samples: 833 of event 'cpu-clock', Event count (approx.): 97742399
Overhead Shared Object Symbol
7.28% perf [.] 0x00000000001f78a4
4.72% [kernel] [k] vsnprintf
4.32% [kernel] [k] module_get_kallsym
3.65% [kernel] [k] _raw_spin_unlock_irqrestore
...
第一行包含三个数据,分别为采样数(833)、事件类型(CPU 时钟事件)和事件总数量(97742399)。
下面是一个表格:
查看某个 CPU 使用率较高的进程所调用的函数
$ top
top - 15:09:17 up 1:26, 1 user, load average: 0.04, 0.04, 0.17
Tasks: 180 total, 1 running, 178 sleeping, 0 stopped, 1 zombie
%Cpu(s): 0.9 us, 1.4 sy, 0.0 ni, 97.6 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st
KiB Mem : 1789476 total, 158556 free, 708816 used, 922104 buff/cache
KiB Swap: 1533948 total, 1531888 free, 2060 used. 849432 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1399 root 20 0 544612 129108 38152 S 3.0 7.2 0:54.46 Xorg
3690 yjp 20 0 1259864 99408 51396 S 3.0 5.6 1:17.82 compiz
4311 yjp 20 0 685460 39452 29528 S 2.0 2.2 0:09.18 gnome-term+
# -g 开启调用关系分析,-p 指定进程号 1399
$ perf top -g -p 1399
按方向键进行切换,再按回车键向下展开,可发现具体的调用关系。
原因可能为:
对于这类进程,可用 pstree 或 execsnoop 找到它们的父进程,在从父进程所在的应用排查入手。
pstree 可用树状形式显示所有进程之间的关系:
$ pstree | grep stress
|-docker-containe-+-php-fpm-+-php-fpm---sh---stress
| |-3*[php-fpm---sh---stress---stress]
stress 是被 php-fpm 调用的子进程,数量为 3。找到父进程后,可进入 app 内部分析。
execsnoop 所用的 ftrace 是一种常用的动态追踪技术,一般用于分析 Linux 内核的运行时行为。
# 按 Ctrl+C 结束
$ execsnoop
PCOMM PID PPID RET ARGS
sh 30394 30393 0
stress 30396 30394 0 /usr/local/bin/stress -t 1 -d 1
sh 30398 30393 0
stress 30399 30398 0 /usr/local/bin/stress -t 1 -d 1
sh 30402 30400 0
stress 30403 30402 0 /usr/local/bin/stress -t 1 -d 1
sh 30405 30393 0
stress 30407 30405 0 /usr/local/bin/stress -t 1 -d 1
...
可发现,大量的 stress 进程不停启动。
参考
倪朋飞. Linux 性能优化实战.