Linux性能优化笔记--002 CPU篇

Linux性能分析 CPU

四个方向的第一个方向 CPU,本文分为四个篇章:分别为基础篇,案例篇,套路篇,答疑篇

基础篇

平均负载

平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃
进程数,它和 CPU 使用率并没有直接关系。

image

1.所谓可运行状态的进程,是指正在使用 CPU 或者正在等待 CPU 的进程,
也就是我们常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程。

2.不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的,
比如最常见的是等待硬件设备的 I/O 响应,也就是我们在 ps 命令中看到的 D 状态

不可中断举例: 一个向磁盘写数据的进程 在磁盘回复前 为了避免数据不一致 这个进程是不可被打断。

平均负载是单位时间平均活跃进程数量 
最理想的状态是 一个核运行一个进程 这样每个CPU核都充分运行了
比如:
	2个CPU有两个进程 则完全占用
	4个CPU有两个进程 则闲置50%的CPU
	1个CPU则 有一半的进程竞争不到CPU

通过grep 和 wc 计算核的数量 然后通过uptime看平均负载来判断系统是否过载

三个时间长度的平均负载分析场景
1分钟 5 分钟 15分钟
1.相差不大 则系统负载平稳
2.1分钟远远小于15分钟 负载减少
3.1分钟远远大于15分钟 负载增加

例子:
这里我再举个例子,假设我们在一个单 CPU 系统上看到平均负载为 1.73,0.60,7.98,
那么说明在过去 1 分钟内,系统有 73% 的超载,
而在 15 分钟内,有 698% 的超载,从整体趋势来看,系统的负载在降低。

当平均负载高于 CPU 数量 70% 的时候,你就应该分析排查负载高的问题了。一旦负载过高,就可能导致进程响应变慢,进而影响服务的正常功能。


延伸指令:
1.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                //正在登录用户数
而最后三个数字呢,依次则是过去 1 分钟、5 分钟、15 分钟的平均负载(Load Average)。

2.grep和wc
$ grep 'model name' /proc/cpuinfo | wc -l  
2                    //核数量
这段代码的功能是使用 grep 命令在 /proc/cpuinfo 文件中查找包含字符串 'model name' 的行,
并通过管道将结果传递给 wc -l 命令进行行数统计。最后的输出结果是2,
表示找到了2行包含 'model name' 的内容。

CPU使用率

平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。
所以,它不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。
而 CPU 使用率,是单位时间内 CPU 繁忙情况的统计,跟平均负载并不一定完全对应。
比如:
1.CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;
CPU密集型代表使用CPU较多 CPU要持续运算
2.I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
IO密集型代表进程多在阻塞 等待 也会让负载升高 但是使用率不一定高
3.大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。
主要区别就是 活跃的进程 代表了平均负载 而使用CPU的进程 才是CPU使用率
活跃的进程不一定一直使用CPU

平均负载案例

工具介绍:
1.stress
一个Linux压测工具 可以用于生成进程
2.sysstat
包含了常用的Linux性能工具 用来监控分析系统性能。
	mpstat 是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标,
	以及所有 CPU 的平均指标。  用于核的查看
	pidstat 是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 
	以及上下文切换等性能指标。 用于进程的查看

场景1:
$ stress --cpu 1 --timeout 600
这段代码的功能是使用stress工具模拟高负载场景。
其中,--cpu 1表示使用一个CPU核心进行基准测试,--timeout 600表示测试持续的时间为600秒。

# -d 参数表示高亮显示变化的区域
$ watch -d uptime
...,  load average: 1.00, 0.75, 0.39


# -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


# 间隔5秒后输出一组数据 5 1
$ 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 使用stress 在CPU1上 进行模拟 先使用 watch -d uptime 来观察平均负载
使用mpstat 观察CPU使用率 和平均负载进行比较 观察CPU密集型进程的影响
最后使用pidstat 观察是哪个进程

场景2:
首先还是运行 stress 命令,但这次模拟 I/O 压力,即不停地执行 sync(sync 同步即 IO): 
$ stress -i 1 --timeout 600
 $ stress-ng -i 1 --hdd 1 --timeout 600
 而—hdd 则表示读写临时文件
-i 1表示使用1个进程调用sync()

# 显示所有CPU的指标,并在间隔5秒输出一组数据
$ mpstat -P ALL 5 1
Linux 4.15.0 (ubuntu)     09/22/18     _x86_64_    (2 CPU)
13:41:28     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
13:41:33     all    0.21    0.00   12.07   32.67    0.00    0.21    0.00    0.00    0.00   54.84
13:41:33       0    0.43    0.00   23.87   67.53    0.00    0.43    0.00    0.00    0.00    7.74
13:41:33       1    0.00    0.00    0.81    0.20    0.00    0.00    0.00    0.00    0.00   98.99

发现CPU的系统CPU使用率不高 但是iowait高 说明是iowait引起了平均负载的升高

场景3:
开启八个进程 这时候平均负载为8是正常的
$ stress -c 8 --timeout 600
$ uptime
...,  load average: 7.97, 5.93, 3.02

运行mpstat观察各核的CPU使用率
11:57:55 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:58:00 PM  all   99.70    0.00    0.30    0.00    0.00    0.00    0.00    0.00    0.00    0.00
11:58:00 PM    0   99.60    0.00    0.40    0.00    0.00    0.00    0.00    0.00    0.00    0.00
11:58:00 PM    1   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00

运行pidstat观察进程的CPU使用率
Average:      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
Average:      999      9395    0.20    0.00    0.00    0.00    0.20     -  mysqld
Average:        0    321656    0.20    0.00    0.00    0.00    0.20     -  AliYunDun
Average:        0    321669    0.40    0.00    0.00    0.00    0.40     -  AliYunDunMonito
Average:        0    340973   24.85    0.00    0.00   75.35   24.85     -  stress
Average:        0    340974   24.85    0.00    0.00   75.15   24.85     -  stress
Average:        0    340975   24.65    0.00    0.00   75.35   24.65     -  stress
Average:        0    340976   24.85    0.20    0.00   74.95   25.05     -  stress
Average:        0    340977   24.65    0.00    0.00   75.15   24.65     -  stress
Average:        0    340978   24.85    0.00    0.00   75.35   24.85     -  stress
Average:        0    340979   25.05    0.00    0.00   74.95   25.05     -  stress
Average:        0    340980   24.65    0.20    0.00   74.95   24.85     -  stress
Average:        0    341186    0.00    0.20    0.00    0.60    0.20     -  pidstat

观察可以发现 每个核基本跑满了 八个进程 所以平均负载为8 每个核都是百分百运行。
8个stress进程 每个的CPU负载为25%  均分两个核 每个进程75%时间在等待

上下文切换

CPU 寄存器,是 CPU 内置的容量小、但速度极快的内存。而程序计数器,则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。它们都是 CPU 在运行任何任务前,必须的依赖环境,因此也被叫做 CPU 上下文。 程序执行的本质及为内存中加载数据和指令到CPU的寄存器进行运算 即使进程没有运行,多个进程竞争CPU也会导致CPU负载很高

根据任务的不同,CPU上下文切换分为:
1.进程上下文切换
2.线程上下文切换
3.中断上下文切换

进程上下文切换:

1.系统调用造成的上下文切换
进程运行在用户空间和内核空间 分别称为用户态和内核态
用户态到内核态的转换通过系统调用完成
系统调用过程中存在上下文切换
CPU--用户态
系统调用---将CPU寄存器内容暂存---加载内核态指令
系统调用结束 切回用户态

image

系统调用的上下文切换指的是特权模式切换 但实际上CPU的上下文切换还是无法避免的

2.进程间上下文切换
进程1 --- 保存进程1上下文----加载进程2上下文---进程2

image

进程上下文切换时机:
1.时间片耗尽
2.系统资源不足
3.sleep函数主动挂起
4.优先级抢占
5.硬件中断 执行中断服务程序

线程上下文切换
线程是调度的基本单位 进程是资源拥有的基本单位
1.同进程下线程的上下文切换 不需要切换共享资源 仅切换私有数据 寄存器等
2.不同进程下上下文切换 需要切换资源
这可以看做是多线程比多进程的一个优势

中断上下文切换
中断会打断进程的正常调度和运行 进行中断处理程序
中断的上下文切换和进程上下文切换不同,中断上下文仅包含内核态中断服务程序执行的
必要条件包括CPU寄存器 内核堆栈 硬件中断参数等

中断上下午切换的优先级>进程
当中断次数过多,需要去排查性能问题

上下文切换分析方法

工具介绍:
目前(mpstat pidstat)
vmstat 用于分析系统的内存使用情况 也常常用来分析CPU上下文切换和中断次数
pidstat -w 加上w可以查看上下文切换情况
pidstat -wt 查看进程和线程的上下文切换情况
pidstat -w -u    -u代表输出CPU情况


sysbench 是一个多线程的基准测试工具,一般用来评估不同系统参数下的数据库负载情况。

# 每隔5秒输出1组数据
$ 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


cs(context switch)是每秒上下文切换的次数。
in(interrupt)则是每秒中断的次数。
r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
b(Blocked)则是处于不可中断睡眠状态的进程数。

# 每隔5秒输出1组数据
$ pidstat -w 5
Linux 4.15.0 (ubuntu)  09/23/18  _x86_64_  (2 CPU)

08:18:26      UID       PID   cswch/s nvcswch/s  Command
08:18:31        0         1      0.20      0.00  systemd
08:18:31        0         8      5.40      0.00  rcu_sched
...

cswch ,表示每秒自愿上下文切换(voluntary context switches)的次数
nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。

1.使用vmstat查看上下文切换和中断等情况
2.使用pidstat -w  查看进程的切换情况
3.使用pidstat -wt 查看线程的的切换情况
4.到此可以确定上下文切换的源头问题
5.在确定中断上升的原因
	那就是从 /proc/interrupts 这个只读文件中读取。
	/proc 实际上是 Linux 的一个虚拟文件系统,用于内核空间与用户空间之间的通信。
	/proc/interrupts 就是这种通信机制的一部分,提供了一个只读的中断使用情况。
6.watch -d cat /proc/interrupts

这个数值其实取决于系统本身的 CPU 性能。在我看来,如果系统的上下文切换次数比较稳定,
那么从数百到一万以内,都应该算是正常的。但当上下文切换次数超过一万次,
或者切换次数出现数量级的增长时,就很可能已经出现了性能问题。
1.自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其他问题;
2.非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈;
3.中断次数变多了,说明 CPU 被中断处理程序占用,还需要通过查看 /proc/interrupts 文件来分析具体的中断类型。

结合前两节,首先通过uptime查看系统负载,然后使用mpstat结合pidstat来初步判断到底是cpu计算量大还是进程争抢过大或者是io过多,接着使用vmstat分析切换次数,以及切换类型,来进一步判断到底是io过多导致问题还是进程争抢激烈导致问题。

posted @ 2024-07-15 22:49  cc学习之路  阅读(45)  评论(0)    收藏  举报