一、服务器CPU简介
CPU的概念:
CPU(Central Processing Unit)又叫中央处理器,其主要功能是进行运算和逻辑运算,内部结构大概可以分为控制单元、算术逻辑单元和存储单元等几个部分。按照其处理信息的字长可以分为:八位微处理器、十六位微处理器、三十二位微处理器以及六十四位微处理器等等。
目前,服务器的CPU仍按CPU的指令系统来区分,通常分为CISC型CPU和RISC型CPU两类,后来又出现了一种64位的VLIM(Very Long Instruction Word超长指令集架构)指令系统的CPU。
- CPU架构:
-
- 复杂指令集CPU:X86架构:如intel、AMD
- 精简指令集CPU:ARM架构如飞腾、PowerPC架构如IBM
- CPU主频:
-
- CPU内核的时钟频率,它是指CPU内部晶振的频率,表示在CPU内数字脉冲信号震荡的速度,常用单位为MHz,它反映了CPU的基本工作节拍,很大程度上影响了CPU的运算速度,CPU的很多性能指标,都会和时钟频率有关,所以一般来说,主频频率越高,CPU每秒处理的数据就越多。
- CPU核心线程:
-
- 我们任务管理器下看到的CPU总数,是你的CPU物理核心数用超线程技术虚拟出来的核心数
- 线程数就是模拟出来的CPU核心数(注意不是CPU物理核心数)
- 对于一个CPU,线程数总是大于或等于核心数(物理核心)的。一个核心(物理核心)最少对应一个线程,但通过超线程技术,一个核心可以对应两个线程,也就是说它可以同时运行两个线程。这也就解释了为什么会有六核心(物理核心)十二线程(CPU核心数)的原因。
- CPU缓存:
-
- 用于减少处理器访问内存所需平均时间的部件。在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存器。其容量远小于内存,但速度却可以接近处理器的频率。
- Architecture: #x86架构/arm架构
- Thread(s) per core: #每个核心的线程数量
- Core(s) per socket: #每颗物理CPU的核数
- CPU socket(s): #物理CPU个数
- CPU MHz: #cpu主频,也就是CPU内核的时钟频率,运算速度
cpu核数计算:
CPU总核数=物理CPU个数 * 每颗物理CPU的核数 =8*1=8
总逻辑CPU数=物理CPU个数 * 每颗物理CPU的核数 * 超线程数* 复用比=8*1*1=8
二、CPU性能指标分类
cpu的性能指标有如下图几种:
三、CPU使用率详解
- 频率:
单位时间内完成振动或振荡的次数或周数 常用单位是赫兹。1赫兹等于1次/秒或1周/秒 频率单位有: Hz(赫)、kHz(千赫)、MHz(兆赫)、GHz(吉赫)。 其中1GHz=1000MHz,1MHz=1000kHz,1kHz=1000Hz[root@localhost hello]# cat /proc/cpuinfo //虚拟机 pc台式机的频率 processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 94 model name : Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
- LINUX系统时钟频率:
LINUX系统时钟频率是一个常数HZ来决定的,如:通常f=3.40GHz,那么他的精度度就是0.29ns(纳秒)。 1GHz周期是1ns。 也就是说每0.29ns一次中断。所以一般来说Linux的精确度是1ns之内。
- 时钟周期:
时钟周期也称为振荡周期,定义为时钟频率的倒数。 时钟周期是计算机中最基本的、最小的时间单位。 在一个时钟周期内,CPU仅完成一个最基本的动作。时钟周期是一个时间的量。 1GHz周期是1ns。 周期单位: s(秒)、ms(毫秒)、μs(微秒)、ns(纳秒), 其中:1s=1000ms,1 ms=1000μs,1μs=1000ns。
- 指令周期:
指令周期(Instruction Cycle):取出并执行一条指令的时间。 计算机执行指令的过程可以分为以下三个步骤: 1.Fetch(取指)也就是从 PC 寄存器里找到对应的指令地址 2.Decode(译码)根据指令寄存器里面的指令,解析成要进行什么样的操作 3.Execute(执行指令)进行算术逻辑操作、数据传输或者直接的地址跳转对于一个指令周期来说,我们取出一条指令,然后执行它,至少需要两个 CPU 周期。 取出指令至少需要一个 CPU 周期,执行至少也需要一个 CPU 周期,复杂的指令则需要更多的 CPU 周期。 而一个CPU周期是若干时钟周期之和。
- CPU时间(monotonic time-mapping - 单调时间变换):
-
- 从操作系统开启算起,CPU就开始工作了,CPU记录自己在工作中总共使用的“时间”的累计值,并把它保存在系统中
- 这些时间由变量jiffies来记录。系统每次启动时jiffies初始化为0,每来一个timer interrupt(时钟中断),jiffies加1,也就是说它代表系统启动后流逝的tick数
- jiffies一定是单调递增的
- jiffies是内核中的一个全局变量,用来记录自系统启动一来产生的时钟中断次数,在linux中,一个中断大致可理解为操作系统进程调度的最小时间片,不同linux内核可能值有不同,通常在1ms到10ms之间
- 全局变量jiffies用来记录自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值。一秒内时钟中断的次数等于Hz,所以jiffies一秒内增加的值也就是Hz。 系统运行时间以秒为单位,等于jiffies/Hz。
- CPU状态类型:
-
- cpu time => cpu user time/sys time/nice time/idle time/irq.....
(默认情况下,top命令以3秒的频率更新输出结果)
参数 | 解析(单位:jiffies 记录系统启动以来产生的节拍数,一个节拍可看为进程调度的最小时间片,jiffies一定是单调递增的) |
user(1204317) | 从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含nice值为负的进程。用户CPU使用率包括用户态 CPU 使用率(user)和低优先级用户态 CPU 使用率(nice),表示 CPU 在用户态运行的时间百分比。用户 CPU 使用率高,通常说明有应用程序比较繁忙。 |
nice(189103) | 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间 |
system(1171340) | 从系统启动开始累计到当前时刻,处于核心态的运行时间。系统CPU使用率表示 CPU 在内核态运行的时间百分比(不包括中断)。系统 CPU 使用率高,说明内核比较繁忙。 |
idle(60581145) | 从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间 |
iowait(90421) | 从系统启动开始累计到当前时刻,IO等待时间。等待 I/O 的 CPU 使用率,通常也称为 iowait,表示等待 I/O 的时间百分比。iowait 高,通常说明系统与硬件设备的 I/O 交互时间比较长。 |
irq(132530) | 从系统启动开始累计到当前时刻,硬中断时间。表示内核调用硬中断处理程序 |
softirq(80465) | 从系统启动开始累计到当前时刻,软中断时间。表示内核调用软中断处理程序 |
stealstolen(0) | 在虚拟机环境下运行其他操作系统所花费的时间。窃取 CPU 使用率(steal)表示被其他虚拟机占用的 CPU 时间百分比 |
guest(0) | 运行在访客模式下所花费的时间。客户 CPU 使用率(guest)表示运行客户虚拟机的 CPU 时间百分比 |
guest_nice(0) | 运行在访客模式下,nice值为负的进程所占用的CPU时间 |
nice值解释:
每一个进程都有一个 PRI 和 NI 值,可通过 ps -ef -l 命令或者top命令查看。PRI 还是比较好理解的,即进程的优先级,或者通俗点说就是程序被 CPU 执行的先后顺序,此值越小进程的优先级别越高。那 NI 呢?就是我们所要说的 nice 值了,其表示进程可被执行的优先级的修正数值。如前面所说,PRI值越小越快被执行,那么加入 nice 值后,将会使得 PRI 变为:PRI(new)=PRI(old)+nice。这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
- 获取CPU各状态当前时间下的累计值:
在/proc伪文件系统中会记录对应的时间累计值,这些总的累计值会存在/proc/stat文件中。
cat /proc/stat 可以观察这些数值
各进程的累计值各自存放在各自的目录文件下,/proc/进程号/stat
- CPU使用率计算原理:
在讲CPU使用率之前,我们来看看下面这个例子: 一台服务器 12:00开机后一直到12:30截止 cpu被使用在用户态 的时间一共是 8分钟 cpu被使用在内核态 的时间一共是 1.5分钟 cpu被使用在IO等待状态 的时间一共是 0.5分钟 cpu被使用在idle(空闲状态) 的时间一共是 20分钟 cpu被使用在其他几个状态的时间是 0分钟(user(8mins) + sys(1.5mins) + iowait(0.5mins) + 0 + 0 + 0 + 0) / (30mins) = 1 - ((idle(20mins) / (30mins)) = 30%cpu的使用率 = (所有非空闲状态的cpu时间总和) / (所有状态cpu时间的总和)= 1 - ((空闲状态cpu时间总和) / (所有状态cpu时间的总和)) (问题:按照上面的方法计算,只能算出cpu在30分钟内的总平均时间,精度太低没参考价值)
上面是从开机开始算的,由于前面我们提到过,jiffies 记录的是系统启动以来产生的节拍数,且jiffies单调递增,那上面cpu使用率的计算公式就要发生变化了,cpu使用率表示的是一定时间下CPU时间增量的变化率:
-
- 采样两个足够短的时间间隔的 cpu 快照,分别为 t1,t2,其中 t1、t2 均包含(user、nice、system、idle、iowait、irq、softirq、stealstolen、 guest)9个元素;
- 计算总的 cpu 时间:
-
-
- 把第一次的所有 cpu 使用情况求和,得到 total_t1;
- 把第二次的所有 cpu 使用情况求和,得到 total_t2;
- 这个时间间隔内的所有时间片,即 totalCpuTime = total_t2 - total_t1 ;
-
-
- 计算空闲时间 idle:
-
-
- idle 对应第四列的数据,用第二次的 idle - 第一次的 idle 即可
- idle = idle_t2 – idle_t1
-
-
- 计算cpu使用率:
-
-
- cpuUsage = 100 * (1-(idle_t2 – idle_t1) / (total_t2 – total_t1))
-
- cpu时间累计递增观察
-
- 我们取30min区间观察CPU0号核cpu idle状态时间数值,通过指标获取,我们可以看到,整体数值是单调递增的
- node_cpu_seconds_total{ instance="192.168.1.190:9100", job="node_exporter", nodename="V6-node-exporter"}
-
- 观察0号CPU核的user状态时间数值,也是递增的
- 使用promethues获取各种指标,计算CPU使用率
-
- 获取CPU时间:
-
-
- 获取各核cpu总时间累计:
-
-
-
-
- node_cpu_seconds_total{ instance="192.168.1.190:9100", job="node_exporter", nodename="V6-node-exporter"}
-
-
-
-
- 获取各核cpu1分钟的时间增量:
-
-
-
-
- increase(node_cpu_seconds_total{ instance="192.168.1.190:9100", job="node_exporter", nodename="V6-node-exporter"}[1m])
-
-
-
-
- 获取各核cpu时间在1分钟内的增量总和:
-
-
-
-
- sum(increase(node_cpu_seconds_total{ instance="192.168.1.190:9100", job="node_exporter", nodename="V6-node-exporter"}[1m]))
-
-
-
- 获取cpu空闲状态时间:
-
-
- 获取各核cpu空闲状态idle时间累计:
-
-
-
-
- node_cpu_seconds_total{ mode="idle",instance="192.168.1.190:9100", job="node_exporter", nodename="V6-node-exporter"}
-
-
-
-
- 获取各核cpu空闲状态时间 在1分钟的增量:
-
-
-
-
- increase(node_cpu_seconds_total{ mode="idle",instance="192.168.1.190:9100", job="node_exporter", nodename="V6-node-exporter"}[1m])
-
-
-
-
- 获取cpu各核空闲状态时间在1分钟内的增量总和:
-
-
-
-
- sum(increase(node_cpu_seconds_total{ mode="idle",instance="192.168.1.190:9100", job="node_exporter", nodename="V6-node-exporter"}[1m])
-
-
-
- 计算系统PU使用率(1分钟增量变化情况):
-
-
- CPU使用率计算公式:
-
-
-
-
- cpuUsage = 100 * (1-(idle_t2 – idle_t1) / (total_t2 – total_t1))
-
-
-
-
- 将变量套进公式:
-
-
-
-
- 100 * (1 - ((sum(increase(node_cpu_seconds_total{ mode="idle",instance="192.168.1.190:9100", job="node_exporter", nodename="V6-node-exporter"}[1m]))) / (sum(increase(node_cpu_seconds_total{ instance="192.168.1.190:9100", job="node_exporter", nodename="V6-node-exporter"}[1m])))))
-
-
四、CPU平均活跃进程数详解(平均负载)(Load Average)
- 平均负载概念:
-
- 平均负载又可以理解成:单位时间的“平均活跃进程数”。这里的活跃进程,主要指可运行状态的进程和不可中断状态的进程。它和CPU使用率没有直接的关系。
- 可运行状态和不可中断状态进程:
-
- 可运行状态进程
-
-
- 可运行状态的进程是指正在使用CPU或者等待CPU的进程,也就是我们通过ps命令能查看到的Running或者Runnable状态的进程。
-
-
- 不可中断状态进程
-
-
- 不可中断进程是指正处于内核关键的进程,这些是不能打断的。也就是我们通过ps命令能查看到的D状态的进程比如,为了保证磁盘数据一致性,回写磁盘的进程就不能打断。不可中断状态是系统对硬件设备的一种保护机制。
-
。。。。。。。。
五、CPU上下文切换
六、CPU缓存命中率
七、CPU运行队列
。。。。。。。。未完待续。。。。。。。。