1. 程式人生 > >cpu負載的探討

cpu負載的探討

sign fix ava 內存 進程 func req and tom

原鏈接:http://blog.chinaunix.net/uid-12693781-id-368837.html

摘要:確定cpu的負載的定義,幫助管理員設置cpu負載閥值,推測可能的導致cpu負載過高的原因,進而保證服務器的正常運行。 1.cpu負載的定義 首先,看看cpu負載的定義。在一般情況下可以將單核心cpu的負載看成是一條單行的橋,數字1代表cpu剛好能夠處理過來,即橋上能夠順利通過所有的車輛, 橋外沒有等待的車輛,橋是暢通的。當超過1時表示有等待上橋的車輛,小於1時表示車輛能夠快速的通過。單核心cpu就表示該cpu能夠處理的事務數是1,在多核 cpu中cpu能夠並行處理的事務的數量應該是cpu個數*cpu核數,而且負載數最好不要超過這個數值。例如一個4核cpu,則cpu_load最大值為4,不能長期超過4,否則會有任務沒有得到及時的處理,而使系統的負載累積增高,導致系統運行緩慢。 大多數的Unix系統中的負載只是記錄那些處在運行狀態和可運行狀態的進程,但是Linux有所不同,它會包含那些不可中斷的處於睡眠狀態的進程。這時當這些進程由於I/O的阻塞而不能夠運行,就可能顯著的增加cpu的負載。所以在Unix和Linux下的cpu的負載的計算方法是不一樣的,在設定監測值的時候也需要特別考率。 下面從內核源碼中分析cpu負載的計算根源,這裏能夠給出cpu負載的完整計算方法。下面的代碼是是在kernel-2.6.32中的kernel/shed.c中截取的,用來計算cpu的平均負載。   技術分享圖片
/* Variables and functions for calc_load */
static atomic_long_t calc_load_tasks;
static unsigned long calc_load_update;
unsigned long avenrun[3];
EXPORT_SYMBOL(avenrun);
 
/**
 * get_avenrun - get the load average array
 * @loads: pointer to dest load array
 * @offset: offset to add
 * @shift: shift count to shift the result left
 *
 * These values are estimates at best, so no need for locking.
 
*/ void get_avenrun(unsigned long *loads, unsigned long offset, int shift) { loads[0] = (avenrun[0] + offset) << shift; loads[1] = (avenrun[1] + offset) << shift; loads[2] = (avenrun[2] + offset) << shift; } static unsigned long calc_load(unsigned long load, unsigned long exp, unsigned long
active) { load *= exp; load += active * (FIXED_1 - exp); return load >> FSHIFT; } /* * calc_load - update the avenrun load estimates 10 ticks after the * CPUs have updated calc_load_tasks. */ void calc_global_load(void) { unsigned long upd = calc_load_update + 10; long active; if (time_before(jiffies, upd)) return; active = atomic_long_read(&calc_load_tasks); active = active > 0 ? active * FIXED_1 : 0; avenrun[0] = calc_load(avenrun[0], EXP_1, active); avenrun[1] = calc_load(avenrun[1], EXP_5, active); avenrun[2] = calc_load(avenrun[2], EXP_15, active); calc_load_update += LOAD_FREQ; } /* * Either called from update_cpu_load() or from a cpu going idle */ static void calc_load_account_active(struct rq *this_rq) { long nr_active, delta; nr_active = this_rq->nr_running; //記錄在cpu上運行的進程數 nr_active += (long) this_rq->nr_uninterruptible; //記錄不可中斷的進程數 if (nr_active != this_rq->calc_load_active) { delta = nr_active - this_rq->calc_load_active; this_rq->calc_load_active = nr_active; atomic_long_add(delta, &calc_load_tasks); } }
View Code

從上面的代碼特別是註釋的兩行可以看出,Linux記錄cpu負載的時候是將cpu隊列中的運行進程數和不可中斷進程數都統計在內的,這樣在對cpu負載分析的時候就需要考慮不可中斷的進程的情況 2.影響cpu負載的進程 從定義可以看出cpu的負載主要來自在cpu運行的進程數,隊列中準備就緒的進程數和不可中斷進程數。那麽當cpu負載過高的時候如果能夠知道當前運行的進程的狀態那麽就能夠判斷是哪些進程的運行導致了問題。剛好,在Linux中ps可以幫助查找當前在運行的進程的狀態,通過對這些進程的狀態的了解,就能夠很好的查找問題的真正原因。
ps aux可以顯示進程的運行狀態
  USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

當使用ps aux後就可以得知一個進程的11項參數,其中STAT是顯示進程的運行狀態。 進程的狀態有以下幾種。
=================進程STAT狀態==================== 
  D 無法中斷的休眠狀態(通常 IO 的進程)
  R 正在運行,在可中斷隊列中; 
  S 處於休眠狀態,靜止狀態; 
  T 停止或被追蹤,暫停執行; 
  W 進入內存交換(從內核2.6開始無效); 
  X 死掉的進程; 
  Z 僵屍進程不存在但暫時無法消除;
  W: 沒有足夠的記憶體分頁可分配
  WCHAN 正在等待的進程資源;
 
  <:高優先級進程
  N: 低優先序進程
  L: 有記憶體分頁分配並鎖在記憶體內 (即時系統或捱A I/O),即,有些頁被鎖進內存
  s 進程的領導者(在它之下有子進程);
  l 多進程的(使用 CLONE_THREAD, 類似 NPTL pthreads);
  + 位於後臺的進程組;

3.防止cpu負載過高的方法 短期來看,可以通過kill和killall來殺死一些影響cpu負載的進程,達到降低cpu負載的目的。 這些進程的狀態是可以利用ps 顯示出來的,然後對相關的進程采取一定的措施就能在短時間內降低cpu的負載。 關於kill和killall的用法,這裏不做詳細的介紹。 4.cpu負載過高的進一步分析 長遠來看,要想cpu的負載不高,就要從cpu的利用率和當前的服務來進行分析。 下面以具體的案例進行分析: 我們有臺服務器,當服務器的鏈接數過高時,就會導致nfs阻塞(該臺服務器和另外一臺服務采用nfs共享文件),這時wa為95.8%,負載馬上就上升到180.
server1:~$ est
    467 connections established
當服務器有大量的鏈接數時會發生nfs阻塞的問題:
root      2631  0.2  0.0      0     0 ?        D    Jul20  50:28 [nfsd]
root      2632  0.2  0.0      0     0 ?        D    Jul20  49:24 [nfsd]
root      2633  0.2  0.0      0     0 ?        S    Jul20  49:27 [nfsd]
root      2634  0.2  0.0      0     0 ?        S    Jul20  49:47 [nfsd]
root      2635  0.2  0.0      0     0 ?        S    Jul20  51:12 [nfsd]
root      2636  0.2  0.0      0     0 ?        S    Jul20  49:00 [nfsd]
root      2637  0.2  0.0      0     0 ?        S    Jul20  49:39 [nfsd]
root      2638  0.2  0.0      0     0 ?        D    Jul20  50:24 [nfsd]

server1:~$ top
 
top - 16:13:12 up 14 days, 21:21,  2 users,  load average: 180.20, 59.85, 22.61
Tasks: 125 total,   1 running, 124 sleeping,   0 stopped,   0 zombie
Cpu :  2.3%us,  1.3%sy,  0.0%ni,  0.0%id, 95.8%wa,  0.0%hi,  0.5%si,  0.0%st
Mem:   2076212k total,  2028752k used,    47460k free,     1804k buffers
Swap:  2104472k total,  1089140k used,  1015332k free,   244076k cached

  

通過這種簡單的分析,就基本上可以斷定問題處在nfs處,需要調整文件共享的方式。 5.關於cpu負載和利用率的關系 大家可以參考這裏的一篇文章寫得很好。 http://www.blogjava.net/cenwenchu/archive/2008/06/30/211712.html

cpu負載的探討