26-CPU知识
CPU
中央处理器
一段程序要被执行,先编译成机器语言
进入内存
cpu控制器再从内存中获取指令、数据,放到寄存器中,
时钟控制cpu的运算器睡眠时候开始计算,计算时长多长
运算器开始计算,运算过程中,如果还需要数据,控制器再从寄存器中拿数据,拿不到就从内存中拿,如果一个时间片段计算不完,就干其他事,之后再执行,执行完了输出数据给寄存器,再传给内存
影响CPU性能的物理因素:主频、架构、核
架构
- Inter(x86)
- AMD(x86)
- IBM(PowerPC)
- ARM
主频
GHz
核心数
单核、双核、n核
CPU的四个组成部分
运算器
运算
控制器
把内存的指令、数据读入寄存器,控制计算机
寄存器
暂存指针、数据、地址
CPU的几级缓存,就是寄存器
时钟
计时
在CPU中进行计算时,都会分配一个时间片段
- 如果某个计算,在分配的时间片段中完成,自动中断
- 如果某个计算,在分配的时间片段中没有完成,强制中断
如果某个任务需要的计算时间比较长,那么cpu的分片就会出现不连续的时间分片
内存
与CPU沟通的桥梁
存cpu的运算数据
硬盘、外存数据
CPU的数据来源
有内存数据
- 内存中的数据
- 外设数据
磁盘数据
执行顺序
CPU中的控制单元,控制指令执行的顺序,并不是按照先后顺序执行,而是按照优先级顺序
运算单元,进行计算时:
- 如果源数据充足
- 如果源数据不够,则会发生等待「iowait」
查看CPU信息
1 | lscpu |
1 | cat /proc/cpuinfo 内存中记录的cpu信息 |
监控cpu
load average值 和CPU使用率之间的关系
现在的linux服务器中 load average 不等于 CPU使用率
load average是系统的整体负载体现,它包括 CPU负载+Disk负载+网络负载+外设负载
load average = cpuload + ioload
CPU的使用:用户进程使用时间us、系统内核运行时间sy、空闲时间idle、管理被抢占时间st
繁忙:us + sy + st + ni + hi + si = CPU使用率的时间(除以总时间)
空闲:idle + wa
- sy:上下文切换「自愿、非自愿」
自愿上下文切换:内存瓶颈
非自愿上下文切换:cpu瓶颈(抢占资源)
- us\ni:用户运行计算 CPU密集计算、FGC、死循环
- si:软中断 CPU竞争
- wa:等待资源 I/O问题(磁盘、网络)
- st:抢占资源(宿主机抢占资源)
CPU上下文
上下文:CPU寄存器和程序计数器
程序计数器:存储CPU正在执行的指令位置和下一条指令的位置
上下文切换:先把当前的任务CPU上下文(CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文到CPU的寄存器和程序计数器中,CPU再跳转到计数器上执行新任务
上下文切换可以分为:
- 进程上下文切换
- 线程上下文切换
- 中断上下文切换
进程:资源的基本单位
线程:调度的基本单位
进程上下文切换:特权等级,跨等级时,需要「系统调用」
- 同进程上下文切换:进程用户态-系统调用-进程内核-系统调用-进程用户态
- 不同进程上下文切换:进程切换时要保存进程用户态资源(虚拟内存,栈等)
线程上下文切换
线程,共享进程的资源,但是线程也有自己所有的数据,如栈、寄存器
同进程中线程上下文切换:进程资源共享,切换线程私有资源
不通进程中线程上下文切换=切换进程
CPU性能分析
load 高&& CPU高
情况1
sy系统态高:排查CPU上下文切换
- 如果「非资源上下文切换」多,说明CPU不够用,进程时间片到,被迫切换
- 如果「自愿上下文切换」多,说明计算用的资源不够用,可能存在I/O、内存瓶颈
1 | root@zx:~# vmstat 1 |
如果cs
比较高,说明可能存在上下文切换问题
1 | root@zx:~# pidstat -u -w 1 |
cswch/s
:自愿上下文
nvcswch/s
:非资源上下文
情况2
si软中断高:CPU抢资源,资源不够用 I/O问题
sys高 + si 高 = 内存或者网络I/O问题
解决办法:排查内存 和 I/O
sys高 + si 不高 = CPU瓶颈
加CPU
情况3
us用户态高:用户程序计算
GC 资源回收
密集型计算、内存FGC、资源等待(线程池)
CPU实战
stress-ng
服务器cpu性能压测工具,模拟系统压力
安装
1 | yum install -y epel-release.noarch && yum -y update |
实操一:进程上下文
进程上下文切换「进程密集型」
1 | 启动N*10个进程,在只有N核的系统上,会产生大量的进程切换,模拟进程间竞争CPU的场景 |
1 | top |
1 | vmstat 1 |
1 | pidstat -u -w 1 |
- top:load值一直在增加 系统负载在升高
- top:CPU的
us
+sy
约等于 100%us
较高sy
较低 - vmstat:procs的 r就绪队列长度,正在运行和等待的CPU进程数很大
- vmstat :system的in「每秒中断次数」和cs「上下文切换次数」都很大
- vmstat:free、buff、cache变化不大
- pidstat:nvcswch/s 非自愿上下文切换在逐步升高
解决办法:项目所在的服务器,
- 减少运行中的进程
- 增加cpu的数量
实操二:线程上下文
1 | 在N核系统上,生成N个进程,每个进程1024个线程,模拟线程间竞争CPU的场景 |
1 | top |
1 | vmstat 1 |
1 | pidstat -u -w 1 |
- top:load值一直在增加,而且增长的非常大
- top:CPU的us + sy 约等于100% us较低、sy较高
- vmstat:procs的r就绪队列长度,正在运行和等待的CPU进程数很大
- vmsta:system的in「每秒中断数」和cs「上下文切换数」都很大
- vmstat:free变小、buff基本不变、cache变大
- free:内存空闲空间,内存消耗增大
- buffer:buffer数磁盘虚拟出来的,用于内存从磁盘读取数据时使用
- cache:cache是内存虚拟出来,用于cpu与内存速度匹配
- pidstat:cswch/s 自愿上下文切换升高
当一个程序开启了大量的线程,就会使用大量的内存资源,就会出现大量的cpu竞争。
从内存中获取数据会有大量的IO数据交换。
解决办法
- 减少项目启动的线程数
- 更换内存速度更高的内存条
- 更换使用CPU的缓存更大的CPU(效果不一定好)
- 改系统的交互分区
实战三:IO密集型
1 | 开启1个worker不停的读写临时文件,同时启动 6个workers不停的调用sync系统调用提交缓存 |
1 | top |
1 | vmstat 1 |
1 | mpstat -P ALL 3 |
1 | pidstat -w 1 |
- top:load值升高,CPU的wa值很大,freeMem变小,buff/cache值增大
- vmstat :memory的free变小,buff基本不变,cache变大,io的bo值非常大「磁盘读写」,CPU的in、cs也都很大
- mpstat:%iowait变得很大,有大量的磁盘IO
- pidstat:cswch/s 自愿上下文切换 变得非常大
解决办法
磁盘性能导致
- 更换读写速度更快的磁盘
- 加大内存
网络IO导致
- 调整网络参数或更换速度更快的网卡