本文为极客时间:《Linux性能优化》学习笔记
简介
常见的性能分析工具,如 I/O 性能问题时,可以参考图片最下方的 I/O 子系统,使用 iostat、iotop、blktrace 等工具分析磁盘 I/O 的瓶颈。
性能分析和优化的思维导图:
一、基础篇
1.1 平均负载
-
平均负载 ≠ CPU使用率
平均负载:单位时间内,系统处于可运行状态
(正在使用 CPU 或者正在等待 CPU 的进程)和不可中断状态
(正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的 I/O 响应)的平均进程数,也就是平均活跃进程数。
CPU使用率:单位时间内 CPU 繁忙情况的统计· CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的; · I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高; · 大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。
-
uptime命令查看系统负载情况:
$ uptime 02:34:03 up 2 days, 20:14, 1 user, load average: 0.63, 0.83, 0.88
具体含义
02:34:03 // 当前时间 up 2 days, 20:14 // 系统运行时间 1 user // 正在登录用户数 load average: 0.63, 0.83, 0.88 // 系统过去1分钟、5分钟、15分钟的平均负载(Load Average),也可用于系统负载趋势判断
-
查看CPU个数
$ grep 'model name' /proc/cpuinfo | wc -l 2
-
平均负载高于CPU数量70%时,通常需要进行负载过高的分析
-
平均负载分析
mpstat 查看 CPU 使用率的变化情况:# -P ALL 表示监控所有 CPU,后面数字 5 表示间隔 5 秒后输出一组数据 $ mpstat -P ALL 5 Linux 4.15.0 (ubuntu) 09/22/18 _x86_64_ (2 CPU) 13:30:06 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 13:30:11 all 50.05 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 49.95 13:30:11 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 13:30:11 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
pidstat 来查询CPU使用率为100%的进程:
# 间隔 5 秒后输出一组数据 $ pidstat -u 5 1 13:37:07 UID PID %usr %system %guest %wait %CPU CPU Command 13:37:12 0 2962 100.00 0.00 0.00 0.00 100.00 1 stress
1.2 CPU上下文切换
-
CPU上下文
CPU寄存器和程序计数器(Program Counter,PC)被称为CPU上下文,CPU寄存器是CPU内置的容量小、速度快的内存;PC是用来存储CPU正在执行或即将执行的下一条指令位置。
-
CPU 上下文切换
先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。 -
CPU 的上下文切换的场景
进程上下文切换、线程上下文切换以及中断上下文切换 -
查看系统的上下文切换情况
假设机器配置为:2 CPU,8GB 内存
vmstat来分析系统的内存使用情况# 每隔 1 秒输出 1 组数据(需要 Ctrl+C 才结束) $ vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 6 0 0 6487428 118240 1292772 0 0 0 0 9019 1398830 16 84 0 0 0 8 0 0 6487428 118240 1292772 0 0 0 0 10191 1392312 16 84 0 0 0 # cs(context switch)是每秒上下文切换的次数。 # in(interrupt)则是每秒中断的次数。 # r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。 # b(Blocked)则是处于不可中断睡眠状态的进程数。 分析: r 列:就绪队列的长度已经到了 8,远远超过了系统 CPU 的个数 2,所以肯定会有大量的 CPU 竞争。 us(user)和 sy(system)列:这两列的 CPU 使用率加起来上升到了 100%,其中系统 CPU 使用率,也就是 sy 列高达 84%,说明 CPU 主要是被内核占用了。 in 列:中断次数也上升到了 1 万左右,说明中断处理也是个潜在的问题。
pidstat查看每个进程上下文切换
# 每隔 1 秒输出 1 组数据(需要 Ctrl+C 才结束) # -w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标 $ pidstat -w -u 1 08:06:33 UID PID %usr %system %guest %wait %CPU CPU Command 08:06:34 0 10488 30.00 100.00 0.00 0.00 100.00 0 sysbench 08:06:34 0 26326 0.00 1.00 0.00 0.00 1.00 0 kworker/u4:2 08:06:33 UID PID cswch/s nvcswch/s Command 08:06:34 0 8 11.00 0.00 rcu_sched 08:06:34 0 16 1.00 0.00 ksoftirqd/1 08:06:34 0 471 1.00 0.00 hv_balloon 08:06:34 0 1230 1.00 0.00 iscsid 08:06:34 0 4089 1.00 0.00 kworker/1:5 08:06:34 0 4333 1.00 0.00 kworker/0:3 08:06:34 0 10499 1.00 224.00 pidstat 08:06:34 0 26326 236.00 0.00 kworker/u4:2 08:06:34 1000 26784 223.00 0.00 sshd # cswch:自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说, I/O、内存等系统资源不足时,就会发生自愿上下文切换 # nvcswch:非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换 分析: 从 pidstat 的输出你可以发现,CPU 使用率的升高是 sysbench 导致的,它的 CPU 使用率已经达到了 100%。但上下文切换则是来自其他进程,包括非自愿上下文切换频率最高的 pidstat ,以及自愿上下文切换频率最高的内核线程 kworker 和 sshd。
pidstat 输出的上下文切换次数,加起来也就几百,比 vmstat 的 139 万明显小了太多。这是怎么回事呢?难道是工具本身出了错吗?
# 每隔 1 秒输出一组数据(需要 Ctrl+C 才结束) # -wt 参数表示输出线程的上下文切换指标 $ pidstat -wt 1 08:14:05 UID TGID TID cswch/s nvcswch/s Command ... 08:14:05 0 10551 - 6.00 0.00 sysbench 08:14:05 0 - 10551 6.00 0.00 |__sysbench 08:14:05 0 - 10552 18911.00 103740.00 |__sysbench 08:14:05 0 - 10553 18915.00 100955.00 |__sysbench 08:14:05 0 - 10554 18827.00 103954.00 |__sysbench ... 分析: 虽然 sysbench 进程(也就是主线程)的上下文切换次数看起来并不多,但它的子线程的上下文切换次数却有很多。看来,上下文切换罪魁祸首,还是过多的 sysbench 线程