查看 CPU 使用率
对于 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 使用率。
- us(user),用户 CPU 时间,不包括 nice 时间,但包括 guest 时间。
- sy(system),内核态 CPU 时间。
- ni(nice),代表低优先级用户态 CPU 时间,即进程的 nice 值被调整为 1-19 之间的 CPU 时间,值越大优先级越低。
- id(idle),空闲时间。
- wa(iowait),等待 I/O 的 CPU 时间。
- hi(irq),处理硬中断的 CPU 时间。
- si(softirq),软中断的 CPU 时间。
- st(steal),系统运行在虚拟机中的时间。
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
...
- %usr,用户态 CPU 使用率。
- %system,内核态 CPU 使用率。
- %guest,运行虚拟机 CPU 使用率。
- %wait,等待 CPU 使用率。
- %CPU,总的 CPU 使用率。
最后会计算 5 组数据的平均值。
CPU 使用率过高怎么办
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)。
下面是一个表格:
- Overhead,该符号的性能事件在所有采样中的比例,以百分比表示。
- Shared,该函数或指令所在的动态共享对象,如内核、进程名、动态链接库名、内核模块名等。
- Object,动态共享对象的类型,[.] 表示用户空间的可执行程序、或动态链接库、[k] 表示内核空间。
- Symbol 是符号名,即函数名。
查看某个 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
按方向键进行切换,再按回车键向下展开,可发现具体的调用关系。
系统的 CPU 使用率很高,但找不到高 CPU 的应用
原因可能为:
- 应用里直接调用了其它二进制程序,这些程序通常运行时间比较端,通过 top 等工具不容易发现。
- 应用本身在不停地崩溃重启,而启动过程的资源初始化,可能会占用较多的 CPU。
对于这类进程,可用 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 性能优化实战.