暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

cpu性能管理的个人总结

大碗岛星期天下午的梦 2020-05-24
635

判断服务器性能,常用到几个指标,cpu、内存、存储、网络等,今天就来简单聊聊cpu。


cpu使用情况,常用两个指标衡量,“平均负载”和“CPU使用率”。“平均负载”用uptime命令查看,“CPU使用率”用top命令。首先区分一下这两个概念,“CPU使用率”很容易理解,就是单位时间内cpu使用繁忙程度。“平均负载”包含正在使用cpu的进程,也包含等待cpu和等待I/O的进程,举个例子,当一个进程需要向磁盘写数据的时候,我们都知道cpu的速度比磁盘快很多,不是一个数量级,因此会出现cpu等待I/O的情况,在这个时候,这个进程在占用着cpu,不可以中断,但是没有使用cpu在运算。


平均负载的定义:单位时间内,处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。

<1>、可运行状态的进程是指:正在使用 CPU 或者正在等待 CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程。

<2>、不可中断状态的进程是指:正处于内核态关键流程中的不可打断的进程,等待硬件设备的 I/O 响应,从ps 命令中看到的 D 状态(Uninterruptible Sleep,也称为 Disk Sleep)进程。当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现磁盘数据与进程数据不一致的问题。不可中断状态实际上是系统对进程和硬件设备的一种保护机制。


在什么情况下会出现平均负载升高,主要有以下三种情况:

<1>、CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时CPU使用率也高;

<2>、I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;

<3>、大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。


下面做几个实验验证一下:


一、cpu密集型

终端运行  stress  命令,模拟一个  CPU  使用率 100% 的场景(实验环境,4核cpu虚拟机,python3)

stress --cpu 1 --timeout 600


top命令:

%user      在internal时间段里,用户态的CPU时间(%),不包含nice值为负进程  (usr/total)*100
%nice 在internal时间段里,nice值为负,的进程的CPU时间(%) (nice/total)*100
%sys 在internal时间段里,内核时间(%) (system/total)*100
%iowait 在internal时间段里,硬盘IO等待时间(%) (iowait/total)*100
%irq 在internal时间段里,硬中断时间(%) (irq/total)*100
%soft 在internal时间段里,软中断时间(%) (softirq/total)*100
%idle 在internal时间段里,CPU除去等待磁盘IO操作外的因为任何原因而空闲的时间闲置时间(%) (idle/total)*100


uptime命令:

ai@ai-virtual-machine:~$ uptime
17:45:45 up 2:07, 1 user, load average: 2.40, 2.01, 1.13
"""
17:45:4 #系统当前时间
up 2:07 #系统运行时间
1 user #正在登录用户数
load average: 2.40, 2.01, 1.13 #cpu在1分钟,5分钟,15分钟内的平均负载
"""


实验结果:

 

从截图看出平均负载不断增高,如果一分钟最大,五分钟,十五分钟最小,说明cpu平均负载正在上升,反正则说明在下降。平均负载的计算方式,数值除cpu核数。例如本次实验用的是4核cpu,当一分钟的平均负载为1时,平均负载为1 / 4 = 0.25,也就是平均负载为25%,从top命令结果看iowait没有升高几乎为0,单个cpu使用率达到了100%,导致了负载变高。注意是user%用户态的cpu使用率达到了100%


二、I/O 密集型进程

终端运行  stress  命令,模拟一模拟  I/O  压力的场景。(实验环境,单核cpu虚拟机,python3)

stress -i 1 --timeout 600

实验结果:

从图二可以看出平均负载在不断升高,从图一来看不仅iowait%高,sys%也非常高,达到了82%,这是怎么回事。实验结果应该I/O高,cpu使用率低才对。下面用perf top命令看一下cpu调用内核情况

可以看到cpu使用前三名分别调用了以下三个内核的函数

66.87%  [kernel]    [k] sync_inodes_sb    
13.00%  [kernel]    [k] _raw_spin_lock      
4.06%  [kernel]     [k] _raw_spin_unlock

此时此刻,应该查看一下内核源码,看下这三个函数的写了啥。然而,我看不懂。。。沉默三个小时


不过百度有非常多关于解读内核的文章,这三个函数作用分别是sync_inodes_sb被用户空间函数调用,用来将缓存中的数据写入块设备,sys_sync系统调用将buffer、inode和super在缓存中的数据写入设备。_raw_spin_lock和_raw_spin_unlock是线程访问共享内存的锁和解锁。我们再回去看一下stress -i 1 --timeout 600这条命令原理是什么,原来这条命令的含义是产生1个进程,反复调用 sync() 将内存上的内容写到硬盘上。说到这,问题就比较好解决了。首先要了解三个概念,用户空间和内核空间,用户态和内核态,cpu上下文切换。


Linux按照特权等级,把进程的运行空间分为内核空间和用户空间。在系统启动的时候,会通过映射开辟一块虚拟空间,分为内核空间和用户空间,内核空间可以直接访问所有资源,用户空间只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源。进程既可以在用户空间运行,又可以在内核空间中运行。进程在用户空间运行时,被称为进程的用户态,而陷入内核空间的时候,被称为进程的内核态。从用户态到内核态的转变,需要通过系统调用来完成。


cpu上下文切换,我们都知道Linux是一个多任务操作系统,支持多于cpu数量的任务同时运行。但其实不是真正的同时运行,而是系统在极短的时间内,将cpu轮流分配给它们,造成同时运行的错觉。在轮流分配的时候,需要不停的中断一个进程,开始另一个进程,这个时候cpu需要知道,这个进程从哪里开始断开,下一次从哪里开始加载运行,也就是说系统需要事先帮它设置好 CPU 寄存器和程序计数器(Program Counter,PC),这两者称为上下文,保存下来的上下文,会存储在系统内核中。所以,保存上一个进程的上下文,加载下一个进程的上下文,称之为上下文切换。根据任务的不同,CPU 的上下文切换就可以分为几个不同的场景,也就是进程上下文切换、线程上下文切换以及中断上下文切换。


那么,上下文切换为什么会导致cpu性能问题?前面说了,用户态到内核态的转变,需要通过系统调用,而stress -i 1 --timeout 600命令就是反复调用 sync() 将内存上的内容写到硬盘上,因此sys内核 态的使用率会升高。


 iowait无法升高的问题,是因为案例中stress使用的是 sync() 系统调用,它的作用是刷新缓冲区内存到磁盘中。对于缓冲区比较小的虚拟机,无法产生大的IO压力,这样大部分就都是系统调用的消耗了。所以,只会看到只有系统CPU使用率升高。


额外补充知识点:

cpu使用率定义:非空闲时间占总 CPU 时间的百分比,非空闲cpu,又可分为用户 CPU、系统 CPU、等待 I/O CPU、软中断和硬中断等。

<1>、用户 CPU 使用率,包括用户态 CPU 使用率(user)和低优先级用户态 CPU 使用率(nice),表示 CPU 在用户态运行的时间百分比。用户 CPU 使用率高,通常说明有应用程序比较繁忙。

<2>、系统 CPU 使用率,表示 CPU 在内核态运行的时间百分比(不包括中断)。系统 CPU 使用率高,说明内核比较繁忙。

<3>、等待 I/O 的 CPU 使用率,通常也称为 iowait,表示等待 I/O 的时间百分比。iowait 高,通常说明系统与硬件设备的 I/O 交互时间比较长。

<4>、软中断和硬中断的 CPU 使用率,分别表示内核调用软中断处理程序、硬中断处理程序的时间百分比。它们的使用率高,通常说明系统发生了大量的中断。


三、大量进程

当系统中运行进程超出 CPU 运行能力时,就会出现等待 CPU 的进程。比如,我们还是使用 stress,但这次模拟的是 8 个进程:

stress -c 8 --timeout 600


实验结果:

可以看出,8 个进程在争抢 4个 CPU,每个进程等待 CPU 的时间(也就是代码块中的 %wait 列)高达 50%。这些超出 CPU 计算能力的进程,最终导致 CPU 过载。



文章转载自大碗岛星期天下午的梦,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论