作者:牛小宝
在进行服务端性能测试时,需要观察系统对CPU的使用情况,以此作为衡量整个系统性能的重要指标,对于Linux CPU主要的关注点在利用率,运行队列,负载,上下文切换等,因此了解这些指标的含义和常用的监控方法对性能测试又很大的帮助。
Linux CPU使用率主要是从以下几个维度进行统计:
一般情况下,CPU大部分的时间片都是消耗在用户态和内核态上,sys和user间的比例是相互影响的,%sys比例高意味着被测服务频繁的进行用户态和系统态之间的切换,会带来一定的CPU开销,这样分配处理业务的时间片就会较少,造成系统性能的下降。对于IO密集型系统,无论是网络IO还是磁盘IO,一般都会产生大量的中断,从而导致%sys相对升高,其中磁盘IO密集型系统,对磁盘的读写需要占用大量的CPU,会导致%iowait的值一定比例的升高,所以当出现%iowait较高时,需排查是否存在大量的不合理的日志操作,或者频繁的数据载入等情况;
CPU利用的详细情况可以通过top,vmstat命令进行查看
%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
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
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
当Linux内核要寻找一个新的进程在CPU上运行时,必须只考虑处于可运行状态的进程,(即在TASK_RUNNING状态的进程),因为扫描整个进程链表是相当低效的,所以引入了可运行状态进程的双向循环链表,也叫运行队列(runqueue)。每个CPU或者说每个核都会维持一个运行队列,队列中存放running和runnable两种状态的进程,CPU会不断的调度队列中的进程运行,因此队列中的进程数越多,每个进程分别到的时间片就越少,程序的时间也就越长,同时CPU会不断的处于运行状态,性能开销较大。可以通过观察一定时间内运行队列中的进程数量来判断CPU是否达到的瓶颈,这就有了负载的概念;
CPU的负载(Load),是指在一段时间内 CPU正在处理以及等待 CPU处理的进程数之和的统计信息,也就是 CPU运行队列长度的统计信息。平均负载(Load Average)是指上一段时间内同时处于运行队列的平均进程数,Load Average是反应系统压力的重要指标,Load Average越高说明对于CPU资源的竞争越激烈,CPU资源比较短缺。对于资源的申请和维护其实也是需要很大的成本,所以在这种高Average Load的情况下CPU资源的长期“热竞争”也是对于硬件的一种损害。
举个例子,把CPU处理进程的过程看成火车站售票:
如果是100,200人或者更多的人买票,这时售票人员就要不停的工作,为了不把售票人员累坏可能就要考虑增加窗口,也就是扩容了。而实际CPU处理进程时并不是像售票一样卖完一个人下一个人,CPU处理每个进程时是有固定的时间片,如果在时间片内这个任务没有处理完,就要挂起这个任务处理下一个,这是就会产生中断,高负载的情况下会不断产生进程间的调用,从而产生大量中断,造成系统的开销,所以在做性能测试时,要重点关注负载情况,来判读CPU是否达到了瓶颈,依据经验分析,单核CPU负载<2时,系统性能是良好的,当单核CPU负载>5时,那么就表明这个机器存在严重的性能问题。
负载可以通过top,uptime、cat /proc/loadavg等命令查看1分钟,5分钟,15分钟的负载值:
top - 10:45:06 up 406 days, 7:29, 5 users, load average: 0.35, 0.63, 0.54
10:45:23 up 406 days, 7:30, 5 users, load average: 0.27, 0.60, 0.53
0.21 0.57 0.52 2/530 32089
一个标准的Linux内核可以支持运行50~50000个进程运行,对于普通的CPU,内核会调度和执行这些进程。每个进程都会分到CPU的时间片来运行,当一个进程用完时间片或者被更高优先级的进程抢占后,它会备份到CPU的运行队列中,同时其他进程在CPU上运行。这个进程切换的过程被称作上下文切换。Linux系统具有两个不同级别的运行模式,内核态和用户态,其中内核态的运行级别要大于用户态,这个级别可以进行任何操作,一般内核运行与内核态,而应用程序是运行在用户态。当发生上下文切换时,通过系统调用,处于用户态的应用程序就会进入内核空间,待调用完成之后重新返回值用户态运行,因此上下文切换存在系统开销,会一定程度上增加%sys的值。
当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够必得到切换时的状态执行下去。在LINUX中,当前进程上下文均保存在进程的任务数据结构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中断服务结束时能恢复被中断进程的执行。
引起上下文切换的原因有哪些? 对于抢占式操作系统而言, 大体有几种:
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
中断是指CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(称为中断服务程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续执行。引入中断的原因有以下几点:
中断根据中断源的不同可以分为硬中断和软中断:
可以通过top,vmstat等查看CPU的相关命令中监控中断情况
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
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
负载和CPU利用率都是衡量CPU性能的指标,那么CPU利用率高的话负载一定高吗?要回答这个问题首先要CPU资源在什么情况下会被消耗,CPU利用率其实是指为了处理进程抢占CPU时间片的比例,也就是只有处于运行状态的进程才会获得时间片,从而造成CPU利用率的上升,而所需CPU时间片的多少取决于进程中需要CPU运算逻辑的复杂程度。而负载是指运行队列中等待和运行的进程数的总和,在负载很高时,可能是出于等待运行的进程数较多,这些进行并不会占用过多的时间片,队列中进程消耗的CPU资源也有可能只是集中在某几个对CPU运算依赖较高的几个进程上。所以CPU利用率和负载之间并没有硬性的比例关联关系,衡量CPU性能时要同时关注两个性能指标,综合考虑。
遇到CPU使用率高时,首先确认CPU是消耗在哪一块,如果是内核态占用CPU较高:
如果是用户态较高,且没有达到预期的性能,说明应用程序需要优化(java应用):
从网上看到一个按照经验给出的指标,可以参考:
3 对于上下文切换要结合CPU使用率来看,如果CPU使用满足上述分布,大量的上下文切换也是可以接受的。
网易云产品免费体验馆,无套路试用,零成本体验云计算价值。
本文来自网易实践者社区,经作者牛小宝授权发布