本文涉及案例来自于学习极客时间专栏《Linux性能优化实战》精心整理而来,案例总结不到位的请各位多多指正。
分析过程
$ top
...
%Cpu0 : 98.7 us, 1.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 99.3 us, 0.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
...
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21514 daemon 20 0 336696 16384 8712 R 41.9 0.2 0:06.00 php-fpm
21513 daemon 20 0 336696 13244 5572 R 40.2 0.2 0:06.08 php-fpm
21515 daemon 20 0 336696 16384 8712 R 40.2 0.2 0:05.67 php-fpm
21512 daemon 20 0 336696 13244 5572 R 39.9 0.2 0:05.87 php-fpm
21516 daemon 20 0 336696 16384 8712 R 35.9 0.2 0:05.61 php-fpm
这里可以看到,系统中有几个 php-fpm 进程的 CPU 使用率加起来接近 200%;而每个 CPU 的用户使用率(us)也已经超过了 98%,接近饱和。这样,我们就可以确认,正是用户空间的 php-fpm 进程,导致 CPU 使用率骤升
# -g开启调用关系分析,-p指定php-fpm的进程号21515
$ perf top -g -p 21515
按方向键切换到 php-fpm,再按下回车键展开 php-fpm 的调用关系,你会发现,调用关系最终到了 sqrt 和 add_function
总结
CPU 使用率是最直观和最常用的系统性能指标,更是我们在排查性能问题时,更要熟悉它每个指标的的含义,尤其要弄清楚用户(%user)、Nice(%nice)、系统(%system) 、等待 I/O(%iowait) 、中断(%irq)以及软中断(%softirq)这几种不同 CPU 的使用率。比如说:
碰到 CPU 使用率升高的问题,你可以借助 top、pidstat 等工具,确认引发 CPU 性能问题的来源;再使用 perf 等工具,排查出引起性能问题的具体函数。
分析过程
$ top
...
%Cpu(s): 80.8 us, 15.1 sy, 0.0 ni, 2.8 id, 0.0 wa, 0.0 hi, 1.3 si, 0.0 st
...
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6882 root 20 0 8456 5052 3884 S 2.7 0.1 0:04.78 docker-containe
6947 systemd+ 20 0 33104 3716 2340 S 2.7 0.0 0:04.92 nginx
7494 daemon 20 0 336696 15012 7332 S 2.0 0.2 0:03.55 php-fpm
7495 daemon 20 0 336696 15160 7480 S 2.0 0.2 0:03.55 php-fpm
10547 daemon 20 0 336696 16200 8520 S 2.0 0.2 0:03.13 php-fpm
10155 daemon 20 0 336696 16200 8520 S 1.7 0.2 0:03.12 php-fpm
10552 daemon 20 0 336696 16200 8520 S 1.7 0.2 0:03.12 php-fpm
15006 root 20 0 1168608 66264 37536 S 1.0 0.8 9:39.51 dockerd
4323 root 20 0 0 0 0 I 0.3 0.0 0:00.87 kworker/u4:1
通过以上输出分析
# 使用 -p 选项指定stress进程的 PID
$ pidstat -p 24344
16:14:55 UID PID %usr %system %guest %wait %CPU CPU Command
没有任何输出。现在终于发现问题,原来这个进程已经不存在了,所以 pidstat 就没有任何输出,而且从top的输出我们看到stress的PID一直在变化,出现这种情况的无非就两个原因:
$ pstree | grep stress
|-docker-containe-+-php-fpm-+-php-fpm---sh---stress
| |-3*[php-fpm---sh---stress---stress]
从这里可以看到,stress 是被 php-fpm 调用的子进程,并且进程数量不止一个(这里是 3 个),接下来就是去看php-fpm的内部代码逻辑了,不在展开
# 记录性能事件,等待大约15秒后按 Ctrl+C 退出
$ perf record -g
# 查看报告
$ perf report
perf输出分析:
总结
碰到常规问题无法解释的 CPU 使用率情况时,首先要想到有可能是短时应用导致的问题,比如有可能是下面这两种情况。
对于短时进程,我们可以通过pstree命令找到它们的父进程,再从父进程所在的应用入手,排查问题的根源
在前一篇文章 Linux系统下CPU性能问题分析案例(上)中我们看到的系统CPU使用率高的表现都是用户态(us)下使用率过高场景的排查过程,关于CPU使用率相关重要指标,我们经常在使用top、dstat、vmstat等工具看到,这里解读一下:
分析过程
从上面的介绍可以看出,iowait升高,第一反应会想到查看系统的 I/O情况,I/O又分为磁盘I/O和网络I/O,这里先分析磁盘I/O
1.运行 dstat 命令,观察 CPU 和 I/O 的使用情况
2.通过pidstat查询进程的I/O情况
# -d:统计进程的磁盘使用情况 1: 采集周期1s 10: 采集10次
pidstat -d 1 10
3.使用ps命令查看下app进程
4.查询app进程的父进程
5.使用perf命令采集性能事件分析app函数调用
# 录制全局性能事件,如果只想录制某个进程的,可以使用-p指定
# perf record -ag -p {pid} -- sleep 10 #采集指定pid所有cpu的性能事件,周期是10s
perf record -g
# 分析报告
perf report
思路总结
你在日常工作中是如何分析CPU的iowait升高的过程的?欢迎一起交流、一起讨论。无论是编码的乐趣还是系统的构建,让我们共同在这个科技的大舞台上创造奇迹。
在我的前一篇文章 Linux系统下CPU性能问题分析案例(中)中介绍了CPU使用率的重要指标,包括User、System、Idle、IOwait、Irq、Softirq、Steal、Guest等CPU时间的说明,通过具体案例分析了User、Iowait等CPU使用率过高的排查思路,感兴趣的可以回去翻看,今天我们来对看下中断对CPU影响的案例和分析过程。
1.使用watch动态观测,确认是什么类型的软中断?
watch -d "/bin/cat /proc/softirqs"
2.使用sar查询网络收发情况
# 使用sar是因为不仅可以观察网络收发的吞吐量(BPS),还可以观察网络收发的网络帧数( PPS)
sar -n DEV 1
3.使用tcpdump抓包一探究竟
tcpdump -i ens33 -n tcp port 80
欢迎一起交流、一起讨论。无论是编码的乐趣还是系统的构建,让我们共同在这个科技的大舞台上创造奇迹。