26-CPU知识

26-CPU知识

CPU

中央处理器

一段程序要被执行,先编译成机器语言

进入内存

cpu控制器再从内存中获取指令、数据,放到寄存器中,

时钟控制cpu的运算器睡眠时候开始计算,计算时长多长

运算器开始计算,运算过程中,如果还需要数据,控制器再从寄存器中拿数据,拿不到就从内存中拿,如果一个时间片段计算不完,就干其他事,之后再执行,执行完了输出数据给寄存器,再传给内存

影响CPU性能的物理因素:主频、架构、核

架构

  • Inter(x86)
  • AMD(x86)
  • IBM(PowerPC)
  • ARM

主频

GHz

核心数

单核、双核、n核

CPU的四个组成部分

cpu组成

运算器

运算

控制器

把内存的指令、数据读入寄存器,控制计算机

寄存器

暂存指针、数据、地址

CPU的几级缓存,就是寄存器

时钟

计时

在CPU中进行计算时,都会分配一个时间片段

  • 如果某个计算,在分配的时间片段中完成,自动中断
  • 如果某个计算,在分配的时间片段中没有完成,强制中断

如果某个任务需要的计算时间比较长,那么cpu的分片就会出现不连续的时间分片

内存

与CPU沟通的桥梁

存cpu的运算数据

硬盘、外存数据

CPU的数据来源

数据

有内存数据

  • 内存中的数据
  • 外设数据

磁盘数据

执行顺序

CPU中的控制单元,控制指令执行的顺序,并不是按照先后顺序执行,而是按照优先级顺序

运算单元,进行计算时:

  • 如果源数据充足
  • 如果源数据不够,则会发生等待「iowait」

查看CPU信息

1
lscpu

lscpu

字段含义

1
2
3
4
cat /proc/cpuinfo 内存中记录的cpu信息
cat /proc/cpuinfo | grep "physical id"|sort |uniq |wc -l 查看物理cpu数量
cat /proc/cpuinfo | grep "cpu cores"|uniq 查看CPU的core数「核数」
cat /proc/cpuinfo | grep "processor"|wc -l 查看逻辑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再跳转到计数器上执行新任务

上下文切换可以分为:

  • 进程上下文切换
  • 线程上下文切换
  • 中断上下文切换

进程:资源的基本单位

线程:调度的基本单位

进程上下文切换:特权等级,跨等级时,需要「系统调用」

  1. 同进程上下文切换:进程用户态-系统调用-进程内核-系统调用-进程用户态
  2. 不同进程上下文切换:进程切换时要保存进程用户态资源(虚拟内存,栈等)

线程上下文切换

线程,共享进程的资源,但是线程也有自己所有的数据,如栈、寄存器

  1. 同进程中线程上下文切换:进程资源共享,切换线程私有资源

  2. 不通进程中线程上下文切换=切换进程

CPU性能分析

load 高&& CPU高

top

情况1

sy系统态高:排查CPU上下文切换

  1. 如果「非资源上下文切换」多,说明CPU不够用,进程时间片到,被迫切换
  2. 如果「自愿上下文切换」多,说明计算用的资源不够用,可能存在I/O、内存瓶颈
1
2
3
4
5
root@zx:~# vmstat 1
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 142112 170316 3332688 0 0 0 5 1 2 1 1 99 0 0
0 0 0 141844 170316 3332728 0 0 0 0 877 1585 1 1 98 0 0

如果cs比较高,说明可能存在上下文切换问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@zx:~# pidstat -u -w 1 
Linux 5.4.0-54-generic (zx) 06/03/2021 _x86_64_ (2 CPU)

08:45:08 PM UID PID %usr %system %guest %wait %CPU CPU Command
08:45:09 PM 0 6095 0.99 0.00 0.00 0.00 0.99 1 dockerd
08:45:09 PM 0 10684 0.99 0.00 0.00 0.00 0.99 1 containerd-shim
08:45:09 PM 0 10776 0.99 0.99 0.00 0.00 1.98 1 gunicorn
08:45:09 PM 0 479183 0.00 1.98 0.00 0.00 1.98 1 AliYunDun
08:45:09 PM 0 503082 0.00 0.99 0.00 0.00 0.99 0 kworker/0:1-events

08:45:08 PM UID PID cswch/s nvcswch/s Command
08:45:09 PM 0 11 40.59 0.00 rcu_sched
08:45:09 PM 0 10708 1.98 0.99 supervisord
08:45:09 PM 0 10775 0.99 0.00 gunicorn
08:45:09 PM 0 479183 10.89 0.00 AliYunDun
08:45:09 PM 0 496341 3.96 0.00 kworker/1:1-events
08:45:09 PM 0 502548 12.87 0.00 kworker/u4:2-events_power_efficient
08:45:09 PM 0 503082 6.93 0.00 kworker/0:1-events
08:45:09 PM 0 503173 0.99 0.00 pidstat

cswch/s :自愿上下文

nvcswch/s:非资源上下文

情况2

si软中断高:CPU抢资源,资源不够用 I/O问题

  1. sys高 + si 高 = 内存或者网络I/O问题

    解决办法:排查内存 和 I/O

  2. sys高 + si 不高 = CPU瓶颈

    加CPU

情况3

us用户态高:用户程序计算

GC 资源回收

密集型计算、内存FGC、资源等待(线程池)

CPU实战

stress-ng

服务器cpu性能压测工具,模拟系统压力

安装

1
2
$ yum install -y epel-release.noarch && yum -y update
$ yum install -y stress-ng

实操一:进程上下文

进程上下文切换「进程密集型」

1
2
3
# 启动N*10个进程,在只有N核的系统上,会产生大量的进程切换,模拟进程间竞争CPU的场景
$ (( proc_cnt = 'nproc'*10 )); stress-ng --cpu $proc_cnt --pthread 1 --timeout 150
stress-ng: info: [504418] dispatching hogs: 2 cpu, 1 pthread
1
$ top

启动后

1
$ vmstat 1

vmstat 1

1
$ pidstat -u -w 1 

pidstat -u -w 1

  1. top:load值一直在增加 系统负载在升高
  2. top:CPU的 us +sy 约等于 100% us较高 sy较低
  3. vmstat:procs的 r就绪队列长度,正在运行和等待的CPU进程数很大
  4. vmstat :system的in「每秒中断次数」和cs「上下文切换次数」都很大
  5. vmstat:free、buff、cache变化不大
  6. pidstat:nvcswch/s 非自愿上下文切换在逐步升高

解决办法:项目所在的服务器,

  • 减少运行中的进程
  • 增加cpu的数量

实操二:线程上下文

1
2
# 在N核系统上,生成N个进程,每个进程1024个线程,模拟线程间竞争CPU的场景
$ stress-ng --cpu `nproc` --pthread 1024 --timeout 60
1
$ top

top

1
$ vmstat 1

vmstat 1

1
$ pidstat -u -w 1 

pidstat -u -w 1

  1. top:load值一直在增加,而且增长的非常大
  2. top:CPU的us + sy 约等于100% us较低、sy较高
  3. vmstat:procs的r就绪队列长度,正在运行和等待的CPU进程数很大
  4. vmsta:system的in「每秒中断数」和cs「上下文切换数」都很大
  5. vmstat:free变小、buff基本不变、cache变大
  • free:内存空闲空间,内存消耗增大
  • buffer:buffer数磁盘虚拟出来的,用于内存从磁盘读取数据时使用
  • cache:cache是内存虚拟出来,用于cpu与内存速度匹配
  1. pidstat:cswch/s 自愿上下文切换升高

当一个程序开启了大量的线程,就会使用大量的内存资源,就会出现大量的cpu竞争。

从内存中获取数据会有大量的IO数据交换。

解决办法

  • 减少项目启动的线程数
  • 更换内存速度更高的内存条
  • 更换使用CPU的缓存更大的CPU(效果不一定好)
  • 改系统的交互分区

实战三:IO密集型

1
2
# 开启1个worker不停的读写临时文件,同时启动 6个workers不停的调用sync系统调用提交缓存
$ stress-ng -i 6 --hdd 1 --timeout 150
1
$ top

top

1
$ vmstat 1

vmstat 1

1
$ mpstat -P ALL 3

mpstat -P ALL 3

1
$ pidstat -w 1

image-20210605101558463

  1. top:load值升高,CPU的wa值很大,freeMem变小,buff/cache值增大
  2. vmstat :memory的free变小,buff基本不变,cache变大,io的bo值非常大「磁盘读写」,CPU的in、cs也都很大
  3. mpstat:%iowait变得很大,有大量的磁盘IO
  4. pidstat:cswch/s 自愿上下文切换 变得非常大

解决办法

磁盘性能导致

  • 更换读写速度更快的磁盘
  • 加大内存

网络IO导致

  • 调整网络参数或更换速度更快的网卡
 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
您的支持将鼓励我继续创作!