進程上下文頻繁切換致使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
相關文章
相關標籤/搜索