一. 上节回顾
1. 什么是进程?什么是线程?它们之间的区别?
2. CPU命令
查看物理CPU的个数
查看每个物理CPU的核数
查看逻辑CPU的个数
3. CPU架构
从处理器层面查看
从操作系统层面查看
4. uptime
load average:三个负载的含义
平均负载和CPU使用率
5. 场景一:CPU密集型进程
二. 场景二:I/O密集型进程
1. 在第一个终端里运行
stress-ng -i 1 --hdd 1 --timeout 600 #hdd表示读写临时文件 或者stress -i 1 --timeout 600 #iowait没有什么变化,效果不明显 或者stress -d 1 -t 600 #查看进程时不太明显,进程占用不是很明显
2. 在第二个终端里运行
watch -d uptime
3. 在第三个终端里使用mpstat查看CPU使用率的变化情况
mpstat -P ALL 5
在运行的过程中,1分钟的平均负载会慢慢不断升高,其中一个CPU使用率升高超过90%以上,iowait也很高,说明平均负载的升高是由于iowait的升高导致的
4. 查看是哪个进程导致的
pidstat -u 5 1
换stress-ng
首先得安装stress-ng,yum install -y stress-ng
三. 场景三:大量进程的场景
当系统中运行进程超出CPU运行能力时,是不是出现等待CPU的进程情况
1. 在第一个终端中模拟12个进程
stress -c 12 --timeout 600
由于系统只有4个CPU,明显比12个进程要少得多,因此系统CPU处于严重过载状态
2. 在第二个终端中使用uptime查看
平均负载高达load average:10.41
3. 在第三个终端运行pidstat -u 5(一直运行,观察多组数据)来看一下进程的情况
可以看出,12个进程在抢夺4个CPU,每个进程等待CPU时间(也就是%wait)高达60%以上,明显超出CPU的计算范围,最终导致CPU过载
总结一下:
CPU使用率,是单位时间内CPU繁忙情况的统计,跟平均负载并不一定完全对应
(1) CPU密集型进程:使用大量CPU会导致平均负载升高,此时这两者是一致的
(2) I/O密集型进程:等待I/O也会导致平均负载升高,但CPU使用率(user%)不一定很高
(3) 大量等待CPU的进程调度也会导致平均负载升高
四. CPU上下文切换
1. 多任务操作系统
Linux是一个多任务操作系统(一台机器可以多个用户同时登录,另外其他人是无感知的),而Windows是单任务操作系统
2. CPU上下文
Linux支持远大于CPU数量的任务同时运行,在每个任务运行前,CPU都需要知道任务从哪里加载,又从哪里开始运行,也就是说,需要系统事先帮它设置好CPU寄存器和程序计数器
CPU寄存器:是CPU内置的容量小,但速度极快的内存
程序计数器:是用来存储CPU正在执行的指令位置,或者即将执行的下一个指令位置
它们都是CPU在运行任何任务前,必须要依赖的环境,因此也被叫做CPU上下文
3. CPU上下文切换
先把前一个任务的CPU上下文(CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务
有人会认为:CPU上下文切换无非就是更新了CPU寄存器的值。这些寄存器,就是为了快速运行任务设计的,为什么影响系统的CPU性能呢?
操作系统管理的这些任务到底是什么?有人会任务:任务就是进程,任务就是线程。是的,进程和线程是最常见的任务,但除此之外,还有没有其他的任务呢?
根据任务的不同,CPU上下文切换可以分为几个不同的场景:
(1) 进程上下文切换
Linux按照特权等级,把进程的运行空间分为内核空间和用户空间,如下图所示:
进程既可以在用户空间运行,又可以在内核空间运行,进程在用户空间运行时,被称为进程的用户态,而在内核空间的时候,被称为进程的内核态
从用户态到内核态的转变,需要通过系统调用来完成,比如:
在查看文件内容时,需要多次系统调用来完成:首先调用open()打开文件,然后调用read()读取文件内容,并调用write()将内容写到标准输出,最后再调用close()关闭文件
进程上下文切换是指一个进程切换到另一个进程运行,而系统在调用过程中一直是同一个进程在运行,所以系统调用的过程通常被称为特权切换模式,而不是上下文切换。系统调用是同一个进程、同一个线程的操作,就像打开文件,就是这个动作去执行了,不会又切换到其他的线程来打开文件操作
(2) 线程上下文切换
线程与进程的最大区别在于:线程是调度的基本单位,而进程是资源拥有的基本单位,所谓内核中的任务调度实际上调度对象是线程,而进程只是给线程提供了虚拟内存、全局变量等资源
对于线程和进程,可以这样理解:
当进程中只有一个线程时,可以认为进程就等于线程
当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源,这些资源在上下文切换时是不需要修改的
另外,线程也有自己的私有数据,比如栈和寄存器,这些在上下文切换时也是需要保存的,这样,线程的上下文也可以分为两种情况:
第一种:前后两个线程属于不同进程,此时,资源不共享,所以切换过程就跟进程上下文切换是一样的
第二种:前后两个线程属于同一个进程,此时因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保存不动,只需要切换线程的私有数据、寄存器等不共享的数据
(3) 中断上下文切换
为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理事件,响应设备事件,而在打断其他进程时,就需要将进程当前状态保存下来,这样在中断结束后,进程仍然可以从原来的状态恢复运行
中断上下文只包括内核态中断服务程序执行所必须的状态,包括CPU寄存器,内核堆栈,硬件中断参数等
对同一个CPU来说,中断处理比进程拥有更高的优先级,所以中断上下文切换并不会和进程上下文切换同时发生
另外,跟进程上下文切换一样,中断上下文切换也需要消耗CPU,切换次数过多也会耗费大量的CPU,严重降低系统的整体性能,所以,在性能测试过程中,当你发现中断次数过多时,需要注意排查它是个给你的系统带来严重的性能问题
做一个小的总结:
不管是哪种场景导致的上下文切换,都应该知道:
CPU上下文切换,是保证Linux系统正常工作的核心功能之一,一般情况下是不需要我们特别关注,但过多的上下文切换,会把CPU时间消耗在寄存器上、内核栈以及虚拟内存等数据的保存和恢复上,从而缩短进程真正运行的时间,导致系统的整体性能大幅下降
4. 怎么查看系统的上下文切换情况
vmstat:是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也可用来分析CPU上下文切换和中断的次数
vmstat 5 # 5:每5s更新一次
procs
r:表示运行和等待CPU时间片的进程数,这个值如果长期大于系统CPU的个数,说明CPU不足,需要增加CPU
b:表示在等待资源的进程数,比如正在等待I/O或者内存交换
------memory------
swpd:表示切换到内存交换区的内存大小(单位:KB),通俗讲就是虚拟内存的大小。如果swap的值不为0或者比较大,只要si,so的值长期为0,这个情况一般属于正常的
free:表示当前空闲的物理内存(单位:KB)
buff:表示bufferscached内存大小,也就是缓冲大小,一般对块设备的读写才需要缓冲
cache:表示pagecached的内存大小,也就是缓冲大小,一般作为系统进行缓冲。频繁访问的文件都会被缓存,如果cache值非常大说明缓存文件比较多,如果此时io中的bi比较小,说明文件系统效率比较好
------swap------
si:表示由磁盘调入内存,也就是内存进入内存交换区的内存大小
so:表示由内存进入磁盘,也就是内存交换区进入内存的内存大小
一般情况下:si,so的值都为0,如果si,so的值长期不为0,说明系统内存不足,需要增加系统内存
------io------
bi:表示由块设备读入数据的总量,即读磁盘,单位kb/s
bo:表示写设备数据的总量,就是写磁盘,单位kb/s
------system------
in:表示某一时间间隔内的每秒设备中断数
cs:表示每次产生的上下文切换次数
------cpu------
us:用户进程消耗的CPU时间百分比,us值越高,说明用户进程消耗CPU时间越多,如果长期大于80%以上,就需要考虑优化程序或者算法
sy:表示系统内核进程消耗的CPU时间百分比,一般来说us + sy应该小于80%,如果大于80%,说明可能CPU处于瓶颈
id:表示CPU处于空闲状态的时间百分比
wa:表示等待CPU的时间百分比,wa值越高,说明I/O等待越严重,根据经验wa的参考值为20%,如果超过20%,说明I/O等待严重,引起I/O等待的原因可能是磁盘大量随机读写造成的,也可能是磁盘的块操作造成的
st:
通过上面的描述,如果要来评估CPU,需要重点关注procs的r列值和CPU项的us,sy,wa列的值,system的in,cs的值