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中,当前进程上下文均保存在进程的任务数据结构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中断服务结束时能恢复被中断进程的执行。
引起上下文切换的原因有哪些? 对于抢占式操作系统而言, 大体有几种:
- 当前任务的时间片用完之后,系统CPU正常调度下一个任务;
- 当前任务碰到IO阻塞,调度线程将挂起此任务,继续下一个任务;
- 多个任务抢占锁资源,当前任务没有抢到,被调度器挂起,继续下一个任务;
- 用户代码挂起当前任务,让出CPU时间;
- 硬件中断;
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暂时中断正在运行的程序,转去执行一段特殊的服务程序(称为中断服务程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续执行。引入中断的原因有以下几点:
- 提高数据传输率;
- 避免了CPU不断检测外设状态的过程,提高了CPU的利用率。
- 实现对特殊事件的实时响应。如多任务系统操作系统中缺页中断、设备中断、各类异常、实时钟等
中断根据中断源的不同可以分为硬中断和软中断:
- 硬中断: 硬中断又称外部中断,是由硬件产生,如键盘,鼠标,打印机等。每个设备或设备集都有它自己的中断请求(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较高:
- %iowait 高,这时要重点关注磁盘IO的相关操作,是否存在不合理的写日志操作,数据库操作等;
- %soft或%cs 高,观察CPU负载是否较高、网卡流量是否较大,可不可以精简数据、代码在是否在多线程操作上存在不合适的中断操作等;
- %steal 高,这种情况一般发生在虚拟机上,这时要查看宿主机是否资源超限;
如果是用户态较高,且没有达到预期的性能,说明应用程序需要优化(java应用):
- 可以使用性能组脚本 show-busy-java-threads.sh(top和jstack命令的结合)抓去CPU利用率高的线程堆栈,查看相关操作;
- 也可使用 jprofile 进行CPU热点的监控,操作步骤见wiki:http://doc.hz.netease.com/pages/viewpage.action?pageId=36451057
8、性能指标总结
从网上看到一个按照经验给出的指标,可以参考:
- 对于每一个CPU来说运行队列不要超过2,例如,如果是双核CPU就不要超过4;
- 如果CPU在满负荷运行,应该符合下列分布:
- User Time:65%~70%,如果高于此数值可以考虑对应用程序进行优化;
- System Time:30%~35%,高于此数值时,观察是否有过多的中断或上下文切换;
- Idle:0%~5%
3 对于上下文切换要结合CPU使用率来看,如果CPU使用满足上述分布,大量的上下文切换也是可以接受的。