1. 程式人生 > >上下文切換頻繁,導致load average 過高

上下文切換頻繁,導致load average 過高

一、問題現象

現網有兩臺虛擬機器主機95%的cpu處於idle狀態,記憶體使用率也不是特別高,而主機的load average達到了40多。

二、問題分析

先在主機上通過top、free、ps、iostat 等常用工具分析了下主機的CPU、記憶體、IO使用情況,發現三者都不高。通過vmstat 1 檢視的結果如下:

context switches

從vmstat的輸出結果來看,io項的block in 和block out 並不頻繁。而system項的每稱的中斷數(in)、每秒的上下文切換(cs)特別頻繁。這就造成load avaerage會特別高。大方向上的根因找到了,具體是哪個程序如何頻繁的進行中斷和上下檔案的切換呢?

這裡使用pidstat -w 1 (每秒重新整理輸出上下文切換情況),輸出見下圖:

context switches

從上圖中可以看到有cswch(自願的上下文切換)和nvcswch(非自願的上下文切換)及對應的命令, 出vsftpd佔用的檔案交換比較多。可以看到這裡顯示的cs 值和總值還是有比較大的差距,由於主機上啟動了不止一個vsftpd程序,而且pidstat 通過1秒重新整理的時候並不會顯示所有,通過pidstat -w執行幾次收集所有發現所有的vsftpd程序佔用的cs值疊加和vmstat裡的比較相近了。

將結果通知業務人員後,和業務人員的猜測也一致,由於ftp使用的目錄結構層次較深、檔案數也比較多,業務在備份老的使用目錄並重新建立單層目錄後,觀察一段後,發現load average降下來了,穩定在1以下。

當然這裡只是處理方法的一種,現網中有些程式不好進行這樣的修改的,又不讓讓程序在cpu之間頻繁切換的,也有通過設定固定執行的CPU上進行調優的方法,如下兩個程序執行在0-7號cpu上:

  1. [[email protected] ~]# taskset -c -p 6389
  2. pid 6389's current affinity list: 0-7
  3. [[email protected] ~]# taskset -c -p 6580
  4. pid 6580's current affinity list:0-7

可以通過taskset讓其固定在0-1號cpu上執行:

  1. [[email protected]
    ~]# taskset -c 0,1 -p 6389

這樣做的原理是每當程序在切換到下一個cpu core上進會flush當前的cache資料,指定CPU時會減少這樣的操作,增加程序的處理速度。這個對老的程式調優時比較有效。

三、有關上下文切換

1、上下文切換的理解

什麼是上下檔案切換呢?引用老外的一句話: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之間的共享資料。

2、引起上下文切換的原因

對於搶佔式作業系統而言, 大體有幾種:

  • 當前任務的時間片用完之後,系統CPU正常排程下一個任務;
  • 當前任務碰到IO阻塞,排程執行緒將掛起此任務,繼續下一個任務;
  • 多個任務搶佔鎖資源,當前任務沒有搶到,被排程器掛起,繼續下一個任務;
  • 使用者程式碼掛起當前任務,讓出CPU時間;
  • 硬體中斷;

什麼樣的操作會引起CS,這裡有一篇博文感覺寫的很不錯,雖然其中的程式碼部分並不是理解 。其中有如下幾句話:

linux中一個程序的時間片到期,或是有更高優先順序的程序搶佔時,是會發生CS的,但這些都是我們應用開發者不可控的 ---前面一部分描述的很到位,後面一部分在系統層面和kernel 開發層面可以呼叫nice 或 renice進行設定優先順序以保證某些程式優先在CPU中的佔用時間,但也不能細化到CS層面

站在開發者的角度,我們的程序可以主動地向核心申請進行CS 。操作方法為:休眠當前程序/執行緒;喚醒其他程序/執行緒 。

3、上下文切換測試工具

1、LMbench 是頻寬(讀取快取檔案、記憶體拷貝、讀寫記憶體、管道等)和反應時間(上下文切換、網路、程序建立等)的評測工具;

2、micro-benchmark contextswitch 可以測試不同的CPU在最少多少ns可以進行一次上下檔案切換,再轉化為秒,我們可以確認該處理器每可以進行的上下檔案切換數 ,該工具的使用可以參看tsuna的blog

4、上下文切換的檢視方法

sar -w ,這個只是能看出主機上總的上下檔案切換的情況

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

同樣,vmstat也可以檢視總的上下文切換情況,不過vmstart輸出的結果更多,便比通過對比發現問題:

  1. # vmstat 3
  2. procs -----------memory-------------swap-------io-----system------cpu----
  3. r b swpd free buff cache si so bi bo in cs us sy id wa
  4. 207292249472823402291972000000713790
  5. 007292251808823442291968000184242009011990
  6. 00729225187682344229196800083172015710990
  7. 00729225187682344229196800073122011610990

檢視每個程序或執行緒的上下檔案使用情況,可以使用pidstat命令或者通過檢視proc 。

  1. # pidstat -w 每個程序的context switching情況
  2. # pidstat -wt 細分到每個threads
  3. 檢視proc下的檔案方法如下:
  4. # pid=307
  5. # grep ctxt /proc/$pid/status
  6. voluntary_ctxt_switches:41#自願的上下文切換
  7. nonvoluntary_ctxt_switches:16#非自願的上下文切換

cswch/s: 每秒任務主動(自願的)切換上下文的次數,當某一任務處於阻塞等待時,將主動讓出自己的CPU資源。

nvcswch/s: 每秒任務被動(不自願的)切換上下文的次數,CPU分配給某一任務的時間片已經用完,因此將強迫該程序讓出CPU的執行權。

上下文切換部分零零碎碎先到這裡吧,只是想說明上下文切換還是比較重要的一個指標的。nagios check_mk預設有對上下文的監控,其使用的方法是通過兩/proc/stat檔案裡取到ctxt行,並取兩個時間段之間的差值來確認。

  1. # cat /proc/stat|grep ctxt
  2. ctxt 111751207