进程上下文频繁切换致使load average太高

1、问题现象

现网有两台虚拟机主机95%的cpu处于idle状态,内存使用率也不是特别高,而主机的load average达到了40多。html

2、问题分析

先在主机上经过top、free、ps、iostat 等经常使用工具分析了下主机的CPU、内存、IO使用状况,发现三者都不高。经过vmstat 1 查看的结果以下:linux

从vmstat的输出结果来看,io项的block in 和block out 并不频繁。而system项的每称的中断数(in)、每秒的上下文切换(cs)特别频繁。这就形成load avaerage会特别高。大方向上的根因找到了,具体是哪一个进程如何频繁的进行中断和上下文件的切换呢?ios

这里使用pidstat -w 1 (每秒刷新输出上下文切换状况),输出见下图:git

 从上图中能够看到有cswch(自愿的上下文切换)和nvcswch(非自愿的上下文切换)及对应的命令, 出vsftpd占用的文件交换比较多。能够看到这里显示的cs 值和总值仍是有比较大的差距,因为主机上启动了不止一个vsftpd进程,并且pidstat 经过1秒刷新的时候并不会显示全部,经过pidstat -w执行几回收集全部发现全部的vsftpd进程占用的cs值叠加和vmstat里的比较相近了。github

将结果通知业务人员后,和业务人员的猜想也一致,因为ftp使用的目录结构层次较深、文件数也比较多,业务在备份老的使用目录并从新建立单层目录后,观察一段后,发现load average降下来了,稳定在1如下。缓存

固然这里只是处理方法的一种,现网中有些程序很差进行这样的修改的,又不让让进程在cpu之间频繁切换的,也有经过设置固定运行的CPU上进行调优的方法,以下两个进程运行在0-7号cpu上:工具

[root@www ~]# taskset -c -p 6389
pid 6389's current affinity list: 0-7
[root@www ~]# taskset -c -p 6580
pid 6580's current affinity list: 0-7

能够经过taskset让其固定在0-1号cpu上运行:测试

  1. [root@www ~]# taskset -c 0,1 -p 6389

这样作的原理是每当进程在切换到下一个cpu core上进会flush当前的cache数据,指定CPU时会减小这样的操做,增长进程的处理速度。这个对老的程序调优时比较有效。spa

3、有关上下文切换

一、上下文切换的理解

什么是上下文件切换呢?引用老外的一句话:A context switch (also sometimes referred to as a process switch or a task switch) is the switching of the CPU (central processing unit) from one process or thread to another.更详细的说明能够参看linfo站点 或 维基百科 。操作系统

context switch太高会致使CPU像个搬运工,频繁在寄存器和运行队列之间奔波 ,更多的时间花在了线程切换,而不是真正工做的线程上。直接的消耗包括CPU寄存器须要保存和加载,系统调度器的代码须要执行。间接消耗在于多核cache之间的共享数据。

二、引发上下文切换的缘由

对于抢占式操做系统而言, 大致有几种:

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

什么样的操做会引发CS,这里有一篇博文感受写的很不错,虽然其中的代码部分并非理解 。其中有以下几句话:

linux中一个进程的时间片到期,或是有更高优先级的进程抢占时,是会发生CS的,但这些都是咱们应用开发者不可控的 ---前面一部分描述的很到位,后面一部分在系统层面和kernel 开发层面能够调用nice 或 renice进行设置优先级以保证某些程序优先在CPU中的占用时间,但也不能细化到CS层面。

站在开发者的角度,咱们的进程能够主动地向内核申请进行CS 。操做方法为:休眠当前进程/线程;唤醒其余进程/线程 。

三、上下文切换测试工具

一、LMbench 是带宽(读取缓存文件、内存拷贝、读写内存、管道等)和反应时间(上下文切换、网路、进程建立等)的评测工具;

二、micro-benchmark contextswitch 能够测试不一样的CPU在最少多少ns能够进行一次上下文件切换,再转化为秒,咱们能够确认该处理器每能够进行的上下文件切换数 ,该工具的使用能够参看tsuna的blog

四、上下文切换的查看方法

sar -w ,这个只是能看出主机上总的上下文件切换的状况

# sar -w 1
proc/s
     Total number of tasks created per second.
cswch/s
     Total number of context switches per second.

一样,vmstat也能够查看总的上下文切换状况,不过vmstart输出的结果更多,便比经过对比发现问题:

# vmstat 3
procs -----------memory----------  ---swap-- -----io----  -system-- ----cpu----
 r  b   swpd   free   buff  cache    si   so    bi    bo   in    cs us sy id wa
 2  0   7292 249472  82340 2291972    0    0     0     0    0     0  7 13 79  0
 0  0   7292 251808  82344 2291968    0    0     0   184   24 20090  1  1 99  0
 0  0   7292 251876  82344 2291968    0    0     0    83   17 20157  1  0 99  0
 0  0   7292 251876  82344 2291968    0    0     0    73   12 20116  1  0 99  0

查看每一个进程或线程的上下文件使用状况,可使用pidstat命令或者经过查看proc 。

# pidstat -w   每一个进程的context switching状况
# pidstat -wt  细分到每一个threads
查看proc下的文件方法以下:
# pid=307
# grep ctxt /proc/$pid/status
voluntary_ctxt_switches:        41    #自愿的上下文切换
nonvoluntary_ctxt_switches:     16    #非自愿的上下文切换

cswch/s: 每秒任务主动(自愿的)切换上下文的次数,当某一任务处于阻塞等待时,将主动让出本身的CPU资源。

nvcswch/s: 每秒任务被动(不自愿的)切换上下文的次数,CPU分配给某一任务的时间片已经用完,所以将强迫该进程让出CPU的执行权。

 

上下文切换部分零零碎碎先到这里吧,只是想说明上下文切换仍是比较重要的一个指标的。nagios check_mk默认有对上下文的监控,其使用的方法是经过两/proc/stat文件里取到ctxt行,并取两个时间段之间的差值来确认。

# cat /proc/stat|grep ctxt
ctxt 111751207
相关文章
相关标签/搜索