一、平均负载

定义:单位时间内,系统中处于可运行状态和不可中断状态的平均进程数。
可运行状态的进程:正在使用cpu或者正在等待cpu的进程,即ps aux命令下STAT处于R状态的进程
不可中断状态的进程:处于内核态关键流程中的进程,且不可被打断,如等待硬件设备IO响应,ps命令D状态的进程
理想状态:每个cpu上都有一个活跃进程,即平均负载数等于cpu数
过载经验值:平均负载高于cpu数量70%的时候

2、查看CPU性能相关命令


1、mpstat 是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标,以及所有 CPU 的平均指标。
2、pidstat 是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标。
3、stress 是一个 Linux 系统压力测试工具,这里我们用作异常进程模拟平均负载升高的场景。
4、mpstat 是一个用来分析系统的内存使用情况,也常用来分析 CPU 上下文切换和中断的次数的工具
4、sysbench 是一个多线程的基准测试工具,一般用来评估不同系统参数下的数据库负载情况
命令安装包: apt install stress sysstat sysbench 或 yum install stress sysstat sysbench

3、命令示例

# 显示cpu核数:
lscpu
grep 'model name' /proc/cpuinfo | wc -l

# 显示平均负载,# 显示的顺序是最近1分钟、5分钟、15分钟,从此可以看出平均负载的趋势:
uptime
top
watch -d uptime #: -d 会高亮显示变化的区域

# 压测命令,--cpu cpu压测选项,-i io压测选项,-c 进程数压测选项,--timeout 执行时间
stress
# 模拟一个 CPU 使用率 100% 的场景
stress --cpu 1 --timeout 600
# 模拟 I/O 压力,即不停地执行 sync
stress -i 1 --timeout 600
# 模拟 8 个进程:
stress -c 8 --timeout 600
# stress的下一代stress-ng,它支持更丰富的选项 
stress-ng -i 1 --hdd 1 --timeout 600(--hdd表示读写临时文件)。

# 多核cpu性能分析工具,-P ALL监视所有cpu
mpstat
# -P ALL 表示监控所有CPU,后面数字5表示间隔5秒后输出一组数据
mpstat -P ALL 5

# 进程性能分析工具,-u 显示cpu使用指标
pidstat
# 间隔5秒后输出一组数据
pidstat -u 5 1
# 查看进程上下文切换  -w参数表示输出进程切换指标
pidstat -w 5
# 上述命令这个结果中有两列内容是我们的重点关注对象。
一个是  cswch  ,表示每秒自愿上下文切换(voluntary context switches)的次数
一个是  nvcswch  ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。

# 每隔1秒输出1组数据(需要 Ctrl+C 才结束)
# -w参数表示输出进程切换指标,而-u参数则表示输出CPU使用指标
pidstat -w -u 1
# 每隔1秒输出一组数据(需要 Ctrl+C 才结束)# -wt 参数表示输出线程的上下文切换指标
pidstat -wt 1

# -d 展示 I/O 统计数据,-p 指定进程号,间隔 1 秒输出 3 组数据
$ pidstat -d -p 4344 1 3
06:38:50      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
06:38:51        0      4344      0.00      0.00      0.00       0  app
06:38:52        0      4344      0.00      0.00      0.00       0  app
06:38:53        0      4344      0.00      0.00      0.00       0  app

kB_rd 表示每秒读的 KB 数
kB_wr 表示每秒写的 KB 数
iodelay 表示 I/O 的延迟(单位是时钟周期)

# 查看系统总体的上下文切换情况
vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 7005360  91564 818900    0    0     0     0   25   33  0  0 100  0  0
# 上述vmstat命令结果需要重点关注对象:
cs(context switch)是每秒上下文切换的次数。
in(interrupt)则是每秒中断的次数。
r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
b(Blocked)则是处于不可中断睡眠状态的进程数。

# 以10个线程运行5分钟的基准测试,模拟多线程切换的问题
sysbench --threads=10 --max-time=300 threads run

# 查看中断使用情况
/proc/interrupts 就是这种通信机制的一部分,提供了一个只读的中断使用情况。
# -d 参数表示高亮显示变化的区域
watch -d cat /proc/interrupts

/proc/softirqs 提供了软中断的运行情况;
/proc/interrupts 提供了硬中断的运行情况。

# 排序后查看
watch -d 'cat /proc/interrupts | sort -nr -k 2 ' 

# perf 是 Linux 2.6.31 以后内置的性能分析工具。它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。
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
...

输出结果中,第一行包含三个数据,分别是采样数(Samples)、事件类型(event)和事件总数量(Event count)。
再往下看是一个表格式样的数据,
每一行包含四列,分别是:第一列 Overhead ,是该符号的性能事件在所有采样中的比例,用百分比来表示。
第二列 Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
第三列 Object ,是动态共享对象的类型。比如 [.] 表示用户空间的可执行程序、或者动态链接库,而 [k] 则表示内核空间。
最后一列 Symbol 是符号名,也就是函数名。当函数名未知时,用十六进制的地址来表示。

# perf 第二种常见用法,也就是 perf record 和 perf report。 perf top 虽然实时展示了系统的性能信息,但它的缺点是并不保存数据,也就无法用于离线或者后续的分析。而 perf record 则提供了保存数据的功能,保存后的数据,需要你用 perf report 解析展示。

$ perf record # 按Ctrl+C终止采样
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.452 MB perf.data (6093 samples) ]

$ perf report # 展示类似于perf top的报告

在实际使用中,经常为 perf top 和 perf record 加上 -g 参数,开启调用关系的采样,方便我们根据调用链来分析性能问题。

# -g开启调用关系分析,-p指定进程号
$ perf top -g -p <pid>

$ perf record -ag -- sleep 2;perf report

execsnoop 就是一个专为短时进程设计的工具。它通过 ftrace 实时监控进程的 exec() 行为,并输出短时进程的基本信息,包括进程 PID、父进程 PID、命令行参数以及执行的结果。

dstat 是一个新的性能工具,它吸收了 vmstat、iostat、ifstat 等几种工具的优点,可以同时观察系统的 CPU、磁盘 I/O、网络以及内存使用情况。

# 间隔1秒输出10组数据
$ dstat 1 10
You did not select any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read  writ| recv  send|  in   out | int   csw
  0   0  96   4   0|1219k  408k|   0     0 |   0     0 |  42   885
  0   0   2  98   0|  34M    0 | 198B  790B|   0     0 |  42   138
  0   0   0 100   0|  34M    0 |  66B  342B|   0     0 |  42   135
  0   0  84  16   0|5633k    0 |  66B  342B|   0     0 |  52   177
  0   3  39  58   0|  22M    0 |  66B  342B|   0     0 |  43   144
  0   0   0 100   0|  34M    0 | 200B  450B|   0     0 |  46   147
  0   0   2  98   0|  34M    0 |  66B  342B|   0     0 |  45   134
  0   0   0 100   0|  34M    0 |  66B  342B|   0     0 |  39   131
  0   0  83  17   0|5633k    0 |  66B  342B|   0     0 |  46   168
  0   3  39  59   0|  22M    0 |  66B  342B|   0     0 |  37   134

从 dstat 的输出,我们可以看到,每当 iowait 升高(wai)时,磁盘的读请求(read)都会很大。这说明 iowait 的升高跟磁盘的读请求有关,很可能就是磁盘读导致的。

strace  正是最常用的跟踪进程系统调用的工具。所以,我们从 pidstat 的输出中拿到进程的 PID 号,比如 6082,然后在终端中运行 strace 命令,并用 -p 参数指定 PID 号:

$ strace -p 6082
strace: attach: ptrace(PTRACE_SEIZE, 6082): Operation not permitted


sar 是一个系统活动报告工具,既可以实时查看系统的当前活动,又可以配置保存和报告历史统计数据。
sar  可以用来查看系统的网络收发情况,还有一个好处是,不仅可以观察网络收发的吞吐量(BPS,每秒收发的字节数),还可以观察网络收发的 PPS,即每秒收发的网络帧数。


# -n DEV 表示显示网络收发的报告,间隔1秒输出一组数据
$ sar -n DEV 1
15:03:46        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
15:03:47         eth0  12607.00   6304.00    664.86    358.11      0.00      0.00      0.00      0.01
15:03:47      docker0   6302.00  12604.00    270.79    664.66      0.00      0.00      0.00      0.00
15:03:47           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
15:03:47    veth9f6bbcd   6302.00  12604.00    356.95    664.66      0.00      0.00      0.00      0.05

第一列:表示报告的时间。
第二列:IFACE 表示网卡。
第三、四列:rxpck/s 和 txpck/s 分别表示每秒接收、发送的网络帧数,也就是  PPS。
第五、六列:rxkB/s 和 txkB/s 分别表示每秒接收、发送的千字节数,也就是  BPS。


hping3 是一个可以构造 TCP/IP 协议数据包的工具,可以对系统进行安全审计、防火墙测试等。
# -S参数表示设置TCP协议的SYN(同步序列号),-p表示目的端口为80
# -i u100表示每隔100微秒发送一个网络帧
# 注:如果你在实践过程中现象不明显,可以尝试把100调小,比如调成10甚至1
$ hping3 -S -p 80 -i u100 192.168.0.30

tcpdump 是一个常用的网络抓包工具,常用来分析各种网络问题。

# -i eth0 只抓取eth0网卡,-n不解析协议名和主机名
# tcp port 80表示只抓取tcp协议并且端口号为80的网络帧
$ tcpdump -i eth0 -n tcp port 80
15:11:32.678966 IP 192.168.0.2.18238 > 192.168.0.30.80: Flags [S], seq 458303614, win 512, length 0
...

4、平均负载与cpu使用率的区别

CPU使用率: 单位时间内cpu繁忙情况的统计
情况1:     CPU密集型进程,CPU使用率和平均负载基本一致
情况2:     IO密集型进程,平均负载升高,CPU使用率不一定升高
情况3:     大量等待CPU的进程调度,平均负载升高,CPU使用率也升高

5、不同类型进程观测指标

1. CPU密集型进程case:

mpstat -P ALL 5: -P ALL表示监控所有CPU,5表示每5秒刷新一次数据,观察是否有某个cpu的%usr会很高,但iowait应很低
pidstat -u 5 1:每5秒输出一组数据,观察哪个进程%cpu很高,但是%wait很低,极有可能就是这个进程导致cpu飚高

2. IO密集型进程case:

mpstat -P ALL 5: 观察是否有某个cpu的%iowait很高,同时%usr也较高
pidstat -u 5 1:观察哪个进程%wait较高,同时%CPU也较高
pidstat -d 5 1:观察哪个进程的kB_rd/s  kB_wr/s 的指标较高

3. 大量进程case:

pidstat -u 5 1:观察那些%wait较高的进程是否有很多

6、上下文切换指标分析

1、所谓自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说, I/O、内存等系统资源不足时,就会发生自愿上下文切换。
2、非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换。
1、自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其他问题
2、非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈;
3中断次数变多了,说明 CPU 被中断处理程序占用,还需要通过查看 /proc/interrupts 文件来分析具体的中断类型。

7、proc/stat文档中关于CPU指标的每列含义解析

# 只保留各个CPU的数据
$ cat /proc/stat | grep ^cpu
cpu  169335831 1377 89883767 5568673446 371534 0 20558393 0 0 0
cpu0 42054301 375 22250264 1391370045 98188 0 10453569 0 0 0
cpu1 42477043 326 22569771 1393014458 76358 0 5333512 0 0 0
cpu2 42590047 329 22607739 1392607302 99902 0 2837353 0 0 0
cpu3 42214438 346 22455991 1391681639 97085 0 1933957 0 0 0
# 上述结果每列含义说明
user(通常缩写为 us),代表用户态 CPU 时间。注意,它不包括下面的 nice 时间,但包括了 guest 时间。
nice(通常缩写为 ni),代表低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间。这里注意,nice 可取值范围是 -2019,数值越大,优先级反而越低。
system(通常缩写为 sys),代表内核态 CPU 时间。
idle(通常缩写为 id),代表空闲时间。注意,它不包括等待 I/O 的时间(iowait)。
iowait(通常缩写为 wa),代表等待 I/O 的 CPU 时间。
irq(通常缩写为 hi),代表处理硬中断的 CPU 时间。
softirq(通常缩写为 si),代表处理软中断的 CPU 时间。
steal(通常缩写为 st),代表当系统运行在虚拟机中的时候,被其他虚拟机占用的 CPU 时间。
guest(通常缩写为 guest),代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的 CPU 时间。
guest_nice(通常缩写为 gnice),代表以低优先级运行虚拟机的时间。

8、CPU使用率指标分析

CPU 使用率是最直观和最常用的系统性能指标,更是我们在排查性能问题时,通常会关注的第一个指标。所以我们更要熟悉它的含义,尤其要弄清楚用户(%user)、Nice(%nice)、系统(%system) 、等待 I/O(%iowait) 、中断(%irq)以及软中断(%softirq)这几种不同 CPU 的使用率。

1、用户 CPU 和 Nice CPU 高,说明用户态进程占用了较多的 CPU,所以应该着重排查进程的性能问题。
2、系统 CPU 高,说明内核态占用了较多的 CPU,所以应该着重排查内核线程或者系统调用的性能问题。
3、I/O 等待 CPU 高,说明等待 I/O 的时间比较长,所以应该着重排查系统存储是不是出现了 I/O 问题。
4、软中断和硬中断高,说明软中断或硬中断的处理程序占用了较多的 CPU,所以应该着重排查内核中的中断服务程序。

碰到 CPU 使用率升高的问题,你可以借助 top、pidstat 等工具,确认引发 CPU 性能问题的来源;再使用 perf 等工具,排查出引起性能问题的具体函数。

作者:于浩  创建时间:2022-12-23 17:52
最后编辑:于浩  更新时间:2024-07-18 09:14