Linux CPU性能指标浅析

猪小花1号2018-09-17 11:53

作者:牛小宝


在进行服务端性能测试时,需要观察系统对CPU的使用情况,以此作为衡量整个系统性能的重要指标,对于Linux CPU主要的关注点在利用率,运行队列,负载,上下文切换等,因此了解这些指标的含义和常用的监控方法对性能测试又很大的帮助。


1、CPU使用率

Linux CPU使用率主要是从以下几个维度进行统计:

  • %usr:普通进程在用户模下下执行的时间;
  • %sys:进程在内核模式下的执行时间;
  • %nice:被提高优先级的进程在用户模式下的执行时间;
  • %idle:空闲时间。
  • %iowait:等待I/O完成的时间。
  • %irp:处理硬中断请求花费的时间。
  • %soft:处理软中断请求花费的时间。
  • %steal:是衡量虚拟机CPU的指标,是指分配给本虚拟机的时间片被同一宿主机别的虚拟机占用,一般%steal值较高时,说明宿主机的资源使用已达到瓶颈;

一般情况下,CPU大部分的时间片都是消耗在用户态和内核态上,sys和user间的比例是相互影响的,%sys比例高意味着被测服务频繁的进行用户态和系统态之间的切换,会带来一定的CPU开销,这样分配处理业务的时间片就会较少,造成系统性能的下降。对于IO密集型系统,无论是网络IO还是磁盘IO,一般都会产生大量的中断,从而导致%sys相对升高,其中磁盘IO密集型系统,对磁盘的读写需要占用大量的CPU,会导致%iowait的值一定比例的升高,所以当出现%iowait较高时,需排查是否存在大量的不合理的日志操作,或者频繁的数据载入等情况; 

CPU利用的详细情况可以通过top,vmstat命令进行查看 

  • top:
%Cpu(s): 0.9 us, 0.6 sy, 0.0 ni, 98.4 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st
  • vmstat:
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 1061592 15986 395216 91660 0 0 3 9 0 0 5 1 94 0
  • mpstat:
CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
 all 0.92 0.00 0.50 0.17 0.00 0.00 0.00 4.14 94.27


2、运行队列:

当Linux内核要寻找一个新的进程在CPU上运行时,必须只考虑处于可运行状态的进程,(即在TASK_RUNNING状态的进程),因为扫描整个进程链表是相当低效的,所以引入了可运行状态进程的双向循环链表,也叫运行队列(runqueue)。每个CPU或者说每个核都会维持一个运行队列,队列中存放running和runnable两种状态的进程,CPU会不断的调度队列中的进程运行,因此队列中的进程数越多,每个进程分别到的时间片就越少,程序的时间也就越长,同时CPU会不断的处于运行状态,性能开销较大。可以通过观察一定时间内运行队列中的进程数量来判断CPU是否达到的瓶颈,这就有了负载的概念;


3、负载:

CPU的负载(Load),是指在一段时间内 CPU正在处理以及等待 CPU处理的进程数之和的统计信息,也就是 CPU运行队列长度的统计信息。平均负载(Load Average)是指上一段时间内同时处于运行队列的平均进程数,Load Average是反应系统压力的重要指标,Load Average越高说明对于CPU资源的竞争越激烈,CPU资源比较短缺。对于资源的申请和维护其实也是需要很大的成本,所以在这种高Average Load的情况下CPU资源的长期“热竞争”也是对于硬件的一种损害。
举个例子,把CPU处理进程的过程看成火车站售票:

  • 假如售票处有10个窗口,买票的人只有1个,毫无疑问,这个乘客随便找个窗口买完票就可以拍屁股走人了,而且还有9个售票人员可以喝茶看报纸,这时的平均负载是0.1,售票运作毫无压力;
  • 如果买票的人有10个,那也还好,一个窗口一个人,所有窗口的售票人员都在工作,也可以快速的买到票,这时的平均负载是1,所有的售票窗口都在运作;
  • 如果有20个人在买票,这就要出现排队的情况,售票人员要不停的卖票,直到排队的都买到票,这时平均负载是2,所有售票窗口都在运作,而且出现了排队情况;

如果是100,200人或者更多的人买票,这时售票人员就要不停的工作,为了不把售票人员累坏可能就要考虑增加窗口,也就是扩容了。而实际CPU处理进程时并不是像售票一样卖完一个人下一个人,CPU处理每个进程时是有固定的时间片,如果在时间片内这个任务没有处理完,就要挂起这个任务处理下一个,这是就会产生中断,高负载的情况下会不断产生进程间的调用,从而产生大量中断,造成系统的开销,所以在做性能测试时,要重点关注负载情况,来判读CPU是否达到了瓶颈,依据经验分析,单核CPU负载<2时,系统性能是良好的,当单核CPU负载>5时,那么就表明这个机器存在严重的性能问题。
负载可以通过top,uptime、cat /proc/loadavg等命令查看1分钟,5分钟,15分钟的负载值:

  • top
top - 10:45:06 up 406 days,  7:29,  5 users,  load average: 0.35, 0.63, 0.54
  • uptime
10:45:23 up 406 days,  7:30,  5 users,  load average: 0.27, 0.60, 0.53
  • cat /proc/loadavg
0.21 0.57 0.52 2/530 32089


4、上下文切换

一个标准的Linux内核可以支持运行50~50000个进程运行,对于普通的CPU,内核会调度和执行这些进程。每个进程都会分到CPU的时间片来运行,当一个进程用完时间片或者被更高优先级的进程抢占后,它会备份到CPU的运行队列中,同时其他进程在CPU上运行。这个进程切换的过程被称作上下文切换。Linux系统具有两个不同级别的运行模式,内核态和用户态,其中内核态的运行级别要大于用户态,这个级别可以进行任何操作,一般内核运行与内核态,而应用程序是运行在用户态。当发生上下文切换时,通过系统调用,处于用户态的应用程序就会进入内核空间,待调用完成之后重新返回值用户态运行,因此上下文切换存在系统开销,会一定程度上增加%sys的值。

当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够必得到切换时的状态执行下去。在LINUX中,当前进程上下文均保存在进程的任务数据结构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中断服务结束时能恢复被中断进程的执行。

引起上下文切换的原因有哪些? 对于抢占式操作系统而言, 大体有几种:

  1. 当前任务的时间片用完之后,系统CPU正常调度下一个任务;
  2. 当前任务碰到IO阻塞,调度线程将挂起此任务,继续下一个任务;
  3. 多个任务抢占锁资源,当前任务没有抢到,被调度器挂起,继续下一个任务;
  4. 用户代码挂起当前任务,让出CPU时间;
  5. 硬件中断; 

vmstat中的cs为中断数量

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 0  0  54484 343748 687816 45583564    0    0     1     3    0    0  1  0 99  0


5、中断

中断是指CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(称为中断服务程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续执行。引入中断的原因有以下几点:

  1. 提高数据传输率;
  2. 避免了CPU不断检测外设状态的过程,提高了CPU的利用率。
  3. 实现对特殊事件的实时响应。如多任务系统操作系统中缺页中断、设备中断、各类异常、实时钟等

中断根据中断源的不同可以分为硬中断和软中断:

  • 硬中断: 硬中断又称外部中断,是由硬件产生,如键盘,鼠标,打印机等。每个设备或设备集都有它自己的中断请求(IRQ),基于IRQ,CPU可以将相应的请求分发到对应的硬件驱动上,处理中断的驱动是需要在CPU上运行的,因此中断产生时,CPU会中断当前正在运行的任务来处理中断,在多核的操作系统中,一个中断通常只能中断一颗CPU(核)。
  • 软中断: 软中断又称内部中断,由软件系统本身发给操作系统内核的中断信号。通常是由硬中断处理程序或进程调度程序对操作系统内核的中断,也就是我们常说的系统调用(System Call)。一般情况下软中断是处理I/O请求时发生订单,这些请求会调用内核中的处理I/O的程序,对于某些设备,I/O请求需要被立即处理,而磁盘I/O请求通常可以排队并且可以稍后处理。根据I/O模型的不同,进程或许会被挂起直到I/O完成,此时内核调度器就会选择另一个进程去运行。I/O可以在进程之间产生并且调度过程通常和磁盘I/O的方式是相同。在I/O密集型系统中可能会出现大量的中断请求,中断会产生中断上下文,造成CPU开。

可以通过top,vmstat等查看CPU的相关命令中监控中断情况

  • vmstat中的in为中断数量
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 0  0  54484 343748 687816 45583564    0    0     1     3    0    0  1  0 99  0
  • mpstat中的 %irq %soft分别为硬中断和软中断所占CPU时间片比例
Linux 3.2.0-3-amd64 (app-66.photo.163.org)     12/14/16     _x86_64_    (16 CPU)

11:30:28     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
11:30:28     all    0.63    0.00    0.32    0.06    0.00    0.11    0.00    0.00   98.88


6、负载与CPU利用率的关系

负载和CPU利用率都是衡量CPU性能的指标,那么CPU利用率高的话负载一定高吗?要回答这个问题首先要CPU资源在什么情况下会被消耗,CPU利用率其实是指为了处理进程抢占CPU时间片的比例,也就是只有处于运行状态的进程才会获得时间片,从而造成CPU利用率的上升,而所需CPU时间片的多少取决于进程中需要CPU运算逻辑的复杂程度。而负载是指运行队列中等待和运行的进程数的总和,在负载很高时,可能是出于等待运行的进程数较多,这些进行并不会占用过多的时间片,队列中进程消耗的CPU资源也有可能只是集中在某几个对CPU运算依赖较高的几个进程上。所以CPU利用率和负载之间并没有硬性的比例关联关系,衡量CPU性能时要同时关注两个性能指标,综合考虑。


7、遇到CPU利用率高该如何排查

遇到CPU使用率高时,首先确认CPU是消耗在哪一块,如果是内核态占用CPU较高:

  1. %iowait 高,这时要重点关注磁盘IO的相关操作,是否存在不合理的写日志操作,数据库操作等;
  2. %soft或%cs 高,观察CPU负载是否较高、网卡流量是否较大,可不可以精简数据、代码在是否在多线程操作上存在不合适的中断操作等;
  3. %steal 高,这种情况一般发生在虚拟机上,这时要查看宿主机是否资源超限; 

如果是用户态较高,且没有达到预期的性能,说明应用程序需要优化(java应用):

  1. 可以使用性能组脚本 show-busy-java-threads.sh(top和jstack命令的结合)抓去CPU利用率高的线程堆栈,查看相关操作;
  2. 也可使用 jprofile 进行CPU热点的监控,操作步骤见wiki:http://doc.hz.netease.com/pages/viewpage.action?pageId=36451057


8、性能指标总结

从网上看到一个按照经验给出的指标,可以参考:

  1. 对于每一个CPU来说运行队列不要超过2,例如,如果是双核CPU就不要超过4;
  2. 如果CPU在满负荷运行,应该符合下列分布: 
  • User Time:65%~70%,如果高于此数值可以考虑对应用程序进行优化;
  • System Time:30%~35%,高于此数值时,观察是否有过多的中断或上下文切换;
  • Idle:0%~5% 

   3 对于上下文切换要结合CPU使用率来看,如果CPU使用满足上述分布,大量的上下文切换也是可以接受的。



网易云产品免费体验馆无套路试用,零成本体验云计算价值。  

本文来自网易实践者社区,经作者牛小宝授权发布