上下文切换的案例以及CPU使用率
一. 上节回顾
1. CPU上下文切换:CPU寄存器和程序计数器
2. CPU上下文可以分为几个不同的场景:进程上下文切换,线程上下文切换,中断上下文切换
3. 线程是调度的基本单位,进程是资源拥有的基本单位
二. 自愿上下文切换和非自愿上下文切换
vmstat:只给出了系统总体的上下文切换情况,要想查看每个进程的详细情况,需要pidstat
pidstat -w 5 #每隔5s输出1组数据(重点关注)
cswch/s:表示每秒自愿上下文切换的次数
nvcswch/s:表示每秒非自愿上下文切换的次数
1. 自愿上下文切换
自愿上下文切换是指进程无法获取所需自愿,导致的上下文切换,比如:I/O,内存等系统资源不足时,就会发生自愿上下文切换
2. 非自愿上下文切换
非自愿上下文切换是指进程由于时间片已到等原因,被系统强制调度
3. 案例分析
sysbench是一个多线程的基准测试工具,一般来评估不同系统参数下的数据库负载情况
(1) 安装
a. yum安装
yum install -y sysbench #不需要提前准备包
b. tar.gz包安装
#解压: tar -zxvf 文件名.tar.gz #进入到解压之后的目录 cd 文件名 ./configure #编译安装 make&&make install
(2) 案例操作和分析步骤
a. 在第一个终端里运行sysbench,模拟系统多线程调用的瓶颈
#以10个线程运行5分钟的基准测试,模拟多线程切换的问题 sysbench --threads=10 --max-time=300 threads run
b. 在第二个终端运行vmstat,观察上下文切换情况
vmstat 3
发现:cs列的上下文切换次数从24一下子到100多万,同时观察其他几个指标
r列:就绪队列的长度已经超过5个,超过了系统CPU的个数4,有大量CPU竞争
us(user)和sy(system)列:这两列的CPU使用率加起来上升到80%以上,其中系统CPU使用率,也就是sy列高达71%,说明CPU主要是被内核占用了
in列:中断次数上升到了4万多,说明中断处理也是一个潜在的问题
综合这几个指标,可以知道,系统的就绪队列过长,也就是正在运行和等待CPU的进程数过多,导致了大量的上下文切换,而上下文切换又导致了系统CPU的占用率升高
那么到底是什么进程导致了这些问题?
c. 在第三个终端用pidstat来看一下,CPU和进程上下文切换情况
pidstat -w -u 1 # -w参数,表示输出进程切换指标,-u参数,表示输出CPU使用指标
从pidstat的输出可以发现,CPU的升高果然是sysbench导致的,它的CPU使用率已经达到300%多,但是发现输出的上下文切换次数很小,比vmstat看到的100多万明显小了太多了,这是怎么回事?
我们再来回想一下,前面提到的几种上下文切换场景,其中一点提到,Linux调度的基本单位实际上是线程,而我们的场景sysbench模拟的也是线程调度问题,那么是不是pidstat忽略了线程的数据?
pidstat:默认是显示进程的指标数据,加上 -t 参数,才会输出线程的指标
pidstat -wt 1 # -wt 表示输出线程的上下文切换指标
可以看到,虽然sysbench进程(也就是主线程)的上下文切换次数看起来并不多,但它的子线程的上下文切换却很多,看来,上下文切换的根源,还是过多的sysbench线程
三. CPU使用率
CPU使用率:load average:0.00,0.56,1.60
在性能测试中常用什么指标来描述系统的CPU性能?
估计很多人,可能不是平均负载,也不是CPU上下文切换,而是另一个更直观的指标:CPU使用率
CPU使用率:是单位时间内CPU使用情况的统计,以百分比的形式展示,那CPU使用率是怎么算出来的?
为了维护CPU时间,Linux通过事先定义的节拍率(表示为HZ),触发时间中断,并使用全局变量记录了开机以来的节拍数,每发送一次时间中断,全部变量的值加1
节拍率HZ是内核的可配置选项,可以设置100,250,1000等,不同的系统可能设置不同数值,可以通过下面命令查看:
grep 'CONFIG_HZ=' /boot/config-$(uname -r)
同时,正因为节拍率HZ是内核选项,所以用户空间程序并不能直接访问,为了方便用户空间程序,内核还提供了一个用户空间节拍率USER_HZ,它总是固定为100,也就是1/100秒,这样用户空间程序并不需要关心内核中HZ被设置了多少?因为它看到的总是固定值USER_HZ
Linux通过/proc虚拟文件系统,向用户空间提供了系统内部状态的信息,而/proc/stat提供的就是系统的CPU和任务统计信息,比如说,如果你只关心CPU的话,可以执行下面的命令:
cat /proc/stat | grep ^cp
这里输出的一个表格,其中,第一列表示的是CPU编号,如CPU,CPU0,CPU1,而第一行没有编号为2的CPU,表示的是所有CPU的累加,其他列则表示不同场景下CPU的累加节拍数,它的单位是USER_HZ,也就是10ms(1/100秒),这其实就是不同场景下的CPU时间
(1) 怎么查看CPU使用率
top
top:显示了系统总体的CPU和内存使用情况,以及各个进程的资源使用情况,默认是3s刷新一次
可以发现,top并没有细分进程的用户态CPU和内核态CPU,那要怎么查看每个进程的详细情况呢?是不是上一次用到的pidstat命令,它可以专门分析每个进程的CPU使用情况
pidstat 1 5 # 每隔1s输出一组数据,共输出5组
pidstat命令,CPU使用率如下:
%usr:用户态CPU使用率
%system:内核态CPU使用率
%guest:运行虚拟机CPU使用率
%wait:等待CPU使用率
%cpu:总的CPU使用率
最后Average部分,还计算了5组数据平均值
通过top,ps,pidstat等工具,能够很快找到CPU使用率过高(100%)的进程,接下来,可能又想知道,占用CPU高的进程的代码是哪个函数?或者哪个类里面的方法,只有这样,我们才能更快的,有针对性的进程优化