平均负载及CPU上下文切换
平均负载
平均负载是指单位时间内,系统处于 可运行状态 和 不可中断状态 的平均进程数。简单理解,就是平均活跃进程数。
- 可运行状态:进程正在或等待使用CPU
- 不可中断状态:进程正在等待硬件设备的I/O,是系统对进程和硬件设备的一种保护机制。
最理想的情况是,每个CPU上刚好运行着1个进程,也就是平均负载等于CPU的个数。假如平均负载是2,那么意味着:
- 单核CPU上,有一半的进程竞争不到CPU
- 双核CPU上,所有的CPU刚好被完全占用
- 4核CPU上,意味着CPU有50%的空闲(idle)
注意,这里的核指逻辑核数,比如超线程的双核CPU,相当于4核。
因此,当平均负载比CPU个数还大时,就出现了系统过载。
在生产环境中,一般推荐平均负载不要高于CPU数量的70%
区别CPU使用率
CPU使用率是单位时间内CPU繁忙情况的统计。而平均负载包括正在使用CPU、等待CPU、等待IO的进程。具体来说:
- CPU密集型进程,CPU使用率高,平均负载高
- I/O密集型进程,平均负载高,CPU使用率低
- 大量等待CPU的进程,平均负载高,CPU使用率也会比较高
案例分析
准备工具
linux系统,并安装以下两款工具:yum install stress sysstat
- stress: linux系统压力测试工具
- sysstat:包含了常用的linux性能工具,这里用到它提供的两个命令:
- mpstat: 多核CPU性能分析工具
- pidstat: 进程性能分析工具,可实时查看cpu, 内存,I/O以及上下文切换等指标
场景一:CPU密集型进程
以root身份登录中断,在终端1执行如下命令:
stress --cpu 2 --timeout 600
# 产生2个进程,压测CPU 600秒, 具体命令参考 man stress说明
终端2执行uptime查看平均负载的变化情况
# watch 监测 -d 表示高亮显示变化的部分
watch -d uptimeEvery 2.0s: uptime Wed Dec 26 20:39:47 201820:39:47 up 54 days, 2:56, 4 users, load average: 0.93, 4.30, 3.23
终端3查看CPU使用率变化:
mpstat -P ALL 2 5
# 每两秒刷新下所有CPU的统计报告,一共刷新显示显示5次。如果不指定最后一个5,那么将一直刷新。
mpstat -P ALL 2
Linux 3.10.0-693.11.1.el7.x86_64 (iz2zeap40j01vg100ifsf4z) 12/26/2018 _x86_64_ (2 CPU)08:41:38 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
08:41:43 PM all 33.56 0.00 2.01 0.00 0.00 0.00 0.00 0.00 0.00 64.43
08:41:43 PM 0 17.37 0.00 1.27 0.00 0.00 0.00 0.00 0.00 0.00 81.36
08:41:43 PM 1 92.19 0.00 6.25 0.00 0.00 0.00 0.00 0.00 0.00 1.56# 其中一个CPU的使用率非常高, 但iowait为0,说明平均负载的升高是由CPU使用率高造成的。
使用查看导致CPU升高的进程:
pidstat -u 2 1
# -u 报告CPU的使用率,2 每两秒,1 报告一次
07:57:34 PM UID PID %usr %system %guest %CPU CPU Command
07:57:39 PM 0 9 0.00 0.20 0.00 0.20 1 rcu_sched
07:57:39 PM 0 479 100.00 0.00 0.00 100.00 0 stress
07:57:39 PM 0 1586 0.00 0.20 0.00 0.20 0 aliyun-service
场景二:I/O 密集型进程
stress --io N --timeout 600
# 产生N个进程,模拟IO压力
场景三:大量进程的情况
stress --cpu 8 # 产生8个进程对CPU进行压测
由于系统只有两个CPU,因此系统处于严重过载状态:
uptime查看负载:1分钟平均负载慢慢飙升到 8.97
20:36:39 up 62 days, 2:53, 5 users, load average: 8.97, 5.49, 2.86
mpstat查看CPU统计数据,可以看到CPU 0 和 1 都满了
Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
Average: all 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Average: 0 98.96 0.00 0.52 0.00 0.00 0.52 0.00 0.00 0.00 0.00
Average: 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
pidstat 查看系统任务统计(一个任务相当于一个进程)
Average: UID PID %usr %system %guest %CPU CPU Command
Average: 0 1286 0.49 0.00 0.00 0.49 - java
Average: 0 3270 23.15 0.00 0.00 23.15 - stress
Average: 0 3271 25.62 0.00 0.00 25.62 - stress
Average: 0 3272 23.65 0.00 0.00 23.65 - stress
Average: 0 3273 27.09 0.00 0.00 27.09 - stress
Average: 0 3274 25.12 0.00 0.00 25.12 - stress
Average: 0 3275 21.67 0.00 0.00 21.67 - stress
Average: 0 3276 25.62 0.00 0.00 25.62 - stress
Average: 0 3277 23.15 0.00 0.00 23.15 - stress
Average: 0 6453 0.49 0.00 0.00 0.49 - dockerd
Average: 0 30783 0.00 0.49 0.00 0.49 - celery
CPU上下文切换
当活跃进程数大于CPU数量时,会出现竞争,CPU需要轮流执行这些进程,于是产生CPU上下文切换,这个切换是有开销的,会导致负载升高。
查看CPU上下文切换
vmstat 用来查看虚拟内存,也可以查看一些CPU总体的上下文切换情况。
vmstat 5 1
# 5秒钟输出一组数据
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----r b swpd free buff cache si so bi bo in cs us sy id wa st1 0 0 124980 170900 1002128 0 0 22 14 1 1 2 1 97 0 00 0 0 124740 170900 1002144 0 0 0 1820 1074 1195 2 1 97 0 0
有用参数
- cs: context switch 每秒钟上下文切换次数
- in:interrupt 每秒钟系统中断次数
- r:running or runnable 就绪队列的长度(运行中,等待运行的进程数)
- b:blocked 处于不可中断的进程数(进程正在等待硬件设备的I/O)
使用pidstat -w
查看每个进程的详细情况:
pidstat -w 5Average: UID PID cswch/s nvcswch/s Command
Average: 0 3 0.40 0.00 ksoftirqd/0
Average: 0 9 57.49 0.00 rcu_sched
Average: 0 10 0.20 0.00 watchdog/0
参数:
- cswch/s:voluntary context switches 自愿上下文切换,指进程无法获取所需的自愿(I/O, 内存等系统资源不足时),发生自愿的上下文切换。
- nvcswch/s: non voluntary context switches 非自愿的上下文切换,进程的时间片到期,被系统强制发生的切换。当大量进程争抢CPU时,就会发生非自愿的上下文切换
模拟测试
安装sysbench,多线程基准测试工具:yum install sysbench sysstat
输入如下命令模拟系统多线程调度的瓶颈:
sysbench --threads=10 --max-time=300 threads run
# 运行10个线程,5分钟
新开一个终端,查看上下文切换情况:
vmstat 1 1 # 每秒刷新一次procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----r b swpd free buff cache si so bi bo in cs us sy id wa st9 0 0 296684 171112 1201540 0 0 21 14 2 2 2 1 97 0 06 0 0 296560 171112 1201540 0 0 0 0 3081 1947126 12 88 0 0 06 0 0 296436 171112 1201540 0 0 0 0 3192 2086130 14 86 1 0 0
可以发现如下特点:
- r 就绪队列,长度达到9,超过系统CPU个数(2个)
- in 终端次数达到3000次
- cs 上下文切换次数达到每秒200万次
- us + sy 的cpu使用率加起来达到100%,其中几乎都被sys占用,说明CPU主要被内核占用了
综合以上数据,得出结论:系统的就绪队列过长,导致了大量的上下文切换,大量上下文切换又导致了CPU的占用率升高。
下面我们通过pidstat命令来查看具体情况:
pidstat -wu 1 2
# -w 输出切换指标 -u 输出CPU使用率 1秒刷新一次,一共刷新2次08:58:30 PM UID PID %usr %system %guest %CPU CPU Command
08:58:31 PM 0 1286 1.00 0.00 0.00 1.00 1 java
08:58:31 PM 0 3871 1.00 1.00 0.00 2.00 1 AliYunDun
08:58:31 PM 999 7145 1.00 0.00 0.00 1.00 1 redis-server
08:58:31 PM 0 9626 1.00 0.00 0.00 1.00 1 celery
08:58:31 PM 0 9627 1.00 0.00 0.00 1.00 0 celery
08:58:31 PM 0 11201 31.00 100.00 0.00 100.00 1 sysbench # 100% CPU08:58:30 PM UID PID cswch/s nvcswch/s Command
08:58:31 PM 0 9 65.00 0.00 rcu_sched
08:58:31 PM 0 13 2.00 0.00 ksoftirqd/1
08:58:31 PM 0 266 3.00 0.00 kworker/0:1H
08:58:31 PM 0 271 4.00 0.00 jbd2/vda1-8
08:58:31 PM 0 1267 10.00 0.00 wrapper
08:58:31 PM 0 1439 12.00 0.00 PM2
# ...08:58:31 PM UID PID %usr %system %guest %CPU CPU Command
08:58:32 PM 0 11201 30.00 100.00 0.00 100.00 1 sysbench
08:58:32 PM 0 11213 0.00 1.00 0.00 1.00 1 pidstat08:58:31 PM UID PID cswch/s nvcswch/s Command
08:58:32 PM 0 9 58.00 0.00 rcu_sched
08:58:32 PM 0 13 1.00 0.00 ksoftirqd/1
08:58:32 PM 0 482 1.00 0.00 irqbalance
08:58:32 PM 0 1267 10.00 0.00 wrapper
08:58:32 PM 0 1439 12.00 0.00 PM2
# ...
观察输出,发现sysbench确实导致了CPU使用率升高,但是上下文切换来自其他进程,并且数量加起来都不到3位数,那为什么vmstat中观察到了200万了,这是为什么?
这是因为线程是系统调度的基本单位,而且sysbench模拟的是线程调度。因此,只需加一个-t
参数,就可以查看线程切换了:
pidstat -wut 1 309:09:18 PM UID TGID TID %usr %system %guest %CPU CPU Command
09:09:19 PM 0 1267 - 1.00 0.00 0.00 1.00 1 wrapper
09:09:19 PM 0 - 3818 1.00 0.00 0.00 1.00 0 |__AliYunDunUpdate
09:09:19 PM 0 - 3872 1.00 0.00 0.00 1.00 0 |__AliYunDun
09:09:19 PM 0 11290 - 34.00 100.00 0.00 100.00 1 sysbench
09:09:19 PM 0 - 11291 4.00 15.00 0.00 19.00 0 |__sysbench
09:09:19 PM 0 - 11292 3.00 16.00 0.00 19.00 1 |__sysbench
09:09:19 PM 0 - 11293 3.00 15.00 0.00 18.00 1 |__sysbench
09:09:19 PM 0 - 11294 3.00 14.00 0.00 17.00 0 |__sysbench
09:09:19 PM 0 - 11295 3.00 17.00 0.00 20.00 0 |__sysbench
09:09:19 PM 0 - 11296 4.00 19.00 0.00 23.00 0 |__sysbench
09:09:19 PM 0 - 11297 3.00 16.00 0.00 19.00 0 |__sysbench
09:09:19 PM 0 - 11298 4.00 16.00 0.00 20.00 0 |__sysbench
09:09:19 PM 0 - 11299 3.00 15.00 0.00 18.00 0 |__sysbench
09:09:19 PM 0 - 11300 3.00 15.00 0.00 18.00 0 |__sysbench
09:09:19 PM 0 11302 - 0.00 1.00 0.00 1.00 1 pidstat
09:09:19 PM 0 - 11302 0.00 1.00 0.00 1.00 1 |__pidstat09:09:18 PM UID TGID TID cswch/s nvcswch/s Command
# ...
09:09:19 PM 0 9631 - 5.00 0.00 celery
09:09:19 PM 0 - 9631 5.00 0.00 |__celery
09:09:19 PM 0 - 9668 2.00 0.00 |__celery
09:09:19 PM 0 - 9669 2.00 0.00 |__celery
09:09:19 PM 0 9632 - 4.00 0.00 celery
09:09:19 PM 0 - 9632 4.00 0.00 |__celery
09:09:19 PM 0 - 9674 2.00 0.00 |__celery
09:09:19 PM 0 - 9675 2.00 0.00 |__celery
09:09:19 PM 0 11267 - 1.00 0.00 kworker/1:1
09:09:19 PM 0 - 11267 1.00 0.00 |__kworker/1:1
09:09:19 PM 0 - 11291 22986.00 175294.00 |__sysbench
09:09:19 PM 0 - 11292 28215.00 170894.00 |__sysbench
09:09:19 PM 0 - 11293 23272.00 138182.00 |__sysbench
09:09:19 PM 0 - 11294 34244.00 151715.00 |__sysbench
09:09:19 PM 0 - 11295 31714.00 167521.00 |__sysbench
09:09:19 PM 0 - 11296 20949.00 194500.00 |__sysbench
09:09:19 PM 0 - 11297 30983.00 185232.00 |__sysbench
09:09:19 PM 0 - 11298 28358.00 172171.00 |__sysbench
09:09:19 PM 0 - 11299 29662.00 159875.00 |__sysbench
09:09:19 PM 0 - 11300 27557.00 148900.00 |__sysbench
09:09:19 PM 0 11302 - 2.00 4.00 pidstat
09:09:19 PM 0 - 11302 2.00 4.00 |__pidstat
# ...
从上述输出可以观察到,sysbench的线程的大量切换。
另外,如果要查看中断次数,可以读取这个文件/proc/interrupts
:
/proc 实际上是 Linux 的一个虚拟文件系统,用于内核空间与用户空间之间的通信。/proc/interrupts 就是这种通信机制的一部分,提供了一个只读的中断使用情况。
watch -d cat /proc/interrupts
# 高亮显示中断文件的变动部分Every 2.0s: cat /proc/interrupts Thu Jan 10 21:20:13 2019CPU0 CPU10: 20 0 IO-APIC-edge timer1: 10 0 IO-APIC-edge i80426: 3 0 IO-APIC-edge floppy8: 0 0 IO-APIC-edge rtc09: 0 0 IO-APIC-fasteoi acpi10: 0 0 IO-APIC-fasteoi virtio411: 35 0 IO-APIC-fasteoi uhci_hcd:usb112: 15 0 IO-APIC-edge i804214: 0 0 IO-APIC-edge ata_piix15: 5756484 0 IO-APIC-edge ata_piix24: 0 0 PCI-MSI-edge virtio2-config25: 2673089 5845758 PCI-MSI-edge virtio2-req.026: 1 0 PCI-MSI-edge virtio0-config27: 1868713 37408103 PCI-MSI-edge virtio0-input.028: 349576 44643775 PCI-MSI-edge virtio0-output.029: 0 0 PCI-MSI-edge virtio3-config30: 326128 0 PCI-MSI-edge virtio3-req.031: 0 0 PCI-MSI-edge virtio1-config32: 22 0 PCI-MSI-edge virtio1-virtqueues
NMI: 0 0 Non-maskable interrupts
LOC: 2924265642 2872116981 Local timer interrupts
SPU: 0 0 Spurious interrupts
PMI: 0 0 Performance monitoring interrupts
IWI: 60559294 62135237 IRQ work interrupts
RTR: 0 0 APIC ICR read retries
RES: 296793417 297917656 Rescheduling interrupts
CAL: 18746994 956271 Function call interrupts
TLB: 5927981 5878741 TLB shootdowns
TRM: 0 0 Thermal event interrupts
THR: 0 0 Threshold APIC interrupts
DFR: 0 0 Deferred Error APIC interrupts
MCE: 0 0 Machine check exceptions
从中可以观察到,以下两个参数在不断变化
- Local timer interrupts
- Rescheduling interrupts 重新调度中断(RES),表示唤醒空闲状态的CPU来调度新的任务运行,这是多处理器系统中,调度器用来分散任务到不同CPU的机制
结论
每秒上下文切换次数的大小,取决于CPU性能,一般来说,切换稳定,数值从百到万以内,都算正常:
- cswch/s 切换多,说明进程在等待资源,可能发生了I/O等其他问题
- nvcswch/sq 切换多,说明进程被强制调度,也就是争抢CPU,说明CPU有瓶颈
- 中断次数多了,说明CPU被中断程序占用,具体可以分析 /proc/interrupts文件
平均负载及CPU上下文切换相关推荐
- 平均负载与 CPU 使用率
一.什么是平均负载 正确定义:单位时间内,系统中处于可运行状态和不可中断状态的平均进程数. 错误定义:单位时间内的cpu使用率. 可运行状态的进程:正在使用cpu或者正在等待cpu的进程,即ps au ...
- 1、cpu平均负载和cpu使用率 排查cpu使用高问题
自定义标题 1. CPU 2. CPU 使用率 3. 测试: 4. 总结 1. CPU cpu平均负载 uptime 或 top 查看 cpu 平均负载(平均负载是指单位时间内,系统处于可运行状态和不 ...
- 理解Linux系统平均负载和CPU使用率
CPU 使用率 CPU 使用率就是 CPU 非空闲态运行的时间占比,它反映了 CPU 的繁忙程度.比如,单核 CPU 1s 内非空闲态运行时间为 0.8s,那么它的 CPU 使用率就是 80%:双核 ...
- 【Linux 性能优化系列】Linux 性能优化 -- CPU 性能篇(一) 平均负载、上下文切换、CPU 使用率
[Linux 性能优化系列]Linux 性能优化 -- CPU 性能篇(一) 平均负载.上下文切换.CPU 使用率 [1]相关概念 [1.1]平均负载 平均负载是指单位时间内,系统处于可运行状态和不可 ...
- linux cpu平均负载,关于linux系统CPU篇---平均负载
1.什么是平均负载?(load average) 平均负载是指单位时间内平均活跃进程数,包括可运行状态的进程数,以及不可中断状态的进程(如等待IO,等待硬件设备响应) 2.如何查看平均负载? 使用to ...
- Linux性能优化一:CPU优化以及平均负载的理解
文章目录 前言: 什么是系统性能调优 到底怎么理解平均负载 它和CPU使用率的关系 平均负载多少合适 如何分析平均负载 平均负载升高的实战模拟 场景:CPU密集型进程 场景二:I/O密集型程序 前言: ...
- 02丨基础篇:到底应该怎么理解“平均负载”?
每次发现系统变慢时,我们通常做的第一件事,就是执行 top 或者 uptime 命令,来了解系统的负载情况.比如像下面这样,我在命令行里输入了 uptime 命令,系统也随即给出了结果. $ upti ...
- 1 理解Linux系统的“平均负载”
什么是平均负载 我们知道使用top或uptime可以用来了解系统的负载情况. uptime 2 02:34:03 up 2 days, 20:14, 1 user, load average: 0.6 ...
- 项目实战,平均负载过高,最后发现却是这个搞鬼
1.前言 最近在项目上遇到负载均衡过高的问题,分析好几天,还因此移植了一个CPU检测工具,后面在小二哥的指导找到了问题原因,小二哥有些读者应该会比较熟悉,之前发的微信滑动卡顿就是他分析的,他是一个非常 ...
最新文章
- Ubuntu下配置Nginx HTTPS
- 全球首个「活体机器人」生娃!100%青蛙基因,杀不死,可繁衍4世
- Odoo之Field
- java tcp read_【Java TCP/IP Socket】TCP Socket通信中由read返回值造成的的死锁问题(含代码)(转)...
- python注释可以辅助程序调试吗_Python 注释
- codeforces1498 D. Bananas in a Microwave(背包+优化)
- excel连接mysql 数据库
- linux内核head.S文件分析
- SingToken全球首款区块链智能AI音乐钱包
- 内存降价-可以入手啦
- java中mysql.ini_为什么找不到mysql.ini文件,我是放在scr目录下的
- 数字电子技术基础-2-逻辑函数的最小项与最大项
- 【数论】范数(norm)
- webp格式图片如何简单快速转换成JPG、PNG格式
- android 修改手机型号加点,修改Android设备信息,如修改手机型号为iPhone7黄金土豪版! -电脑资料...
- 照片太大怎么缩小kb?
- 终极文件/文件夹隐藏方案大全
- 微信小程序开发账号找回
- Combined Cycle Power Plant Data Set(初学练手:详解)
- Java生成word文档|综合