平均負載與 CPU 使用率,到底有啥區(qū)別?
?大家好,我是樹哥。
在性能優(yōu)化中,我們經(jīng)常會關(guān)注 CPU 平均負載這個指標。但如果讓你來跟我解釋一下什么是平均負載,你能說得清楚嗎?它跟 CPU 使用率有什么區(qū)別?我想可能很多人都數(shù)不清楚,今天我們就來盤一盤 CPU 平均負載這個指標!
平均負載與 CPU 使用率,到底有啥區(qū)別?
Linux 進程狀態(tài)
要弄明白 CPU 平均負載,我們還需要從 Linux 進程狀態(tài)說起。
在 Linux 源碼的 fs/proc/array.c 文件中,其定義了進程的 7 種狀態(tài),如下所示:
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
第一種狀態(tài):TASK_RUNNING 可執(zhí)行狀態(tài),縮寫 R。
該狀態(tài)表示進程可以在 CPU 上運行,即具備運行的條件。但同一時刻可能有多個進程可以運行,但并不代表該進程已經(jīng)在運行。處于 TASK_RUNNING 的進程會被放入 CPU 的可執(zhí)行隊列中,隨后會被進程調(diào)度器分配到其中一個 CPU 上 運行。
很多操作系統(tǒng)教科書將 CPU 上執(zhí)行的進程定義為 RUNNING 狀態(tài),而將可執(zhí)行但是尚未被調(diào)度執(zhí)行的進程定義為 READY 狀態(tài),這兩種狀態(tài)在 Linux 系統(tǒng)下統(tǒng)一為 TASK_RUNNING 狀態(tài)。
第二種狀態(tài):TASK_INTERRUPTIBLE 可中斷的睡眠狀態(tài),縮寫 S。
該狀態(tài)的進程表示因為等待某某時間的發(fā)生而被掛起,例如:等待 socket 連接、等待信號量等等。這些進程會被放入對應事件的等待隊列中,當這些事件發(fā)生時,對應等待隊列中的一個或多個進程將被喚醒。
通過 ps 命令我們可以看到,絕大多數(shù)進程都處于 TASK_INTERRUPTIBLE 狀態(tài)。這是因為由于 CPU 只有那么幾個,而進程卻動輒幾百上千,因此絕大多數(shù)進程在某個時刻都是處于睡眠狀態(tài)的。如果不是絕大多數(shù)進程都在睡眠,CPU 是無法響應得過來的。
第三種狀態(tài):TASK_UNINTERRUPTIBLE 不可中斷睡眠狀態(tài),縮寫 D。
該狀態(tài)與 TASK_INTERRUPTIBLE 狀態(tài)類似,進程處于睡眠狀態(tài),但唯一不同的點是該進程是不可中斷的。不可中斷指的并不是 CPU 不響應外部硬件的中斷,而是指進程不響應異步信號。
絕大多數(shù)情況下,進程處在睡眠狀態(tài)時,總是應該能夠響應異步信號的。即你能夠通過 kill -15 pid? 方式傳遞異步信號,程序可以做出響應。但有時候你會驚奇地發(fā)現(xiàn),kill -9 竟然殺不死一個正在睡眠的進程了,這時候有可能就是該進程處于不可中斷睡眠狀態(tài)了!
TASK_UNINTERRUPTIBLE 狀態(tài)存在的意義就在于:內(nèi)核的某些處理流程是不能被打斷的,例如:在進程對某些硬件進行操作時,如果產(chǎn)生中斷的話會導致進程與硬件設備交互被打斷,使得設備陷入不可控狀態(tài)。這種情況下的 TASK_UNINTERRUPTIBLE 狀態(tài)總是非常短暫的,通過 ps 命令基本上不可能捕捉到。
第四、五種狀態(tài):TASK_STOPPED 暫停狀態(tài)、TASK_TRACED 狀態(tài),縮寫 T。
當我們向進程發(fā)送一個 SIGSTOP 信號時,它就會因響應該信號而進入 TASK_STOPPED 狀態(tài)。除非該進程本身處于 TASK_UNINTERRUPTIBLE 狀態(tài)而不響應信號)。向進程發(fā)送一個 SIGCONT 信號,可以讓其從 TASK_STOPPED 狀態(tài)恢復到 TASK_RUNNING 狀態(tài)。
第六種狀態(tài):TASK_DEAD - EXIT_ZOMBIE 退出狀態(tài),縮寫 Z。
進程退出之后,進程所占有的所有資源將被回收,隨后該進程就被成為僵尸進程(Zombie)。一般情況下是子進程先于父進程退出,并且父進程沒有調(diào)用 wait 或 waitpid 回收子進程。此時子進程即處于僵尸狀態(tài)。
第七種狀態(tài):TASK_DEAD - EXIT_DEAD 退出狀態(tài),縮寫 X。
進程被置于 EXIT_DEAD 退出狀態(tài),這意味著接下來的代碼立即就會將該進程徹底釋放。一般情況下 EXIT_DEAD 狀態(tài)是非常短暫的,幾乎不可能通過 ps 命令捕捉到。
看完了 Linux 進程的 7 種狀態(tài),是不是有點懵了?其實你只需要記住 Linux 有這 7 種狀態(tài),其中最重要的是 RUNNING 狀態(tài)、UNINTERRUPTIBLE 狀態(tài)就可以了。
我們總結(jié)一下 Linux 的 7 種進程狀態(tài):
- TASK_RUNNING 可執(zhí)行狀態(tài),縮寫 R。
- TASK_INTERRUPTIBLE 可中斷的睡眠狀態(tài),縮寫 S。
- TASK_UNINTERRUPTIBLE 不可中斷睡眠狀態(tài),縮寫 D。
- TASK_STOPPED 暫停狀態(tài)、TASK_TRACED 狀態(tài),縮寫 T。
- TASK_DEAD - EXIT_ZOMBIE 退出狀態(tài),縮寫 Z。
- TASK_DEAD - EXIT_DEAD 退出狀態(tài),縮寫 X。
平均負載的定義
平均負載的定義是:單位時間內(nèi),系統(tǒng)中處于可運行狀態(tài)和不可中斷狀態(tài)的平均進程數(shù)。 這里的可運行狀態(tài)和不可中斷狀態(tài),指的就是上文說到的進程狀態(tài)。從平均負載的定義來看,其與進程所處的狀態(tài)有關(guān)系,因此我們后續(xù)分析平均負載的時候,要以該定義為基礎去分析。
對于有 4 核 CPU 的機器,如果一共運行了 4 個進程,那么每個 CPU 都運行了 1 個進程,此時所有的 CPU 都剛好被完全占用。
而如果只有 2 個進程,那么意味著 CPU 有 50% 的空閑。而如果有 8 個進程,那么意味著 CPU 超載了,平均負載達到了 2,但單位時間內(nèi)單個 CPU 需要運行 2 個進程。
我們可以通過讀取 /proc/cpuinfo 文件獲取系統(tǒng) CPU 信息,如下所示:
$ grep 'model name' /proc/cpuinfo | wc -l2
當平均負載比 CPU 個數(shù)還多的時候,就表示系統(tǒng)已經(jīng)出現(xiàn)了負載。一般情況下,負載不超過 70% 的情況下都是正常的。
很多人都會將 CPU 平均負載與 CPU 使用率搞混,實際上它們有一定關(guān)聯(lián),但不是同一個東西。
平均負載是指單位時間內(nèi),處于可運行狀態(tài)和不可中斷的進程數(shù)。從其定義可以知道,其不僅包括了正在使用 CPU 的進程,還包括等待 CPU 和等待 I/O 的進程。而 CPU 使用率指的是正在使用 CPU 的進程,由此可見它們兩者是不同的。
如果是 CPU 密集型的進程,因為進程大量使用 CPU,因此平均負載會上升,CPU 使用率會上升。但如果是 I/O 密集型進程,有很多進程在等待 I/O 操作,此時進程處于不可中斷狀態(tài),因此平均負載會升高,但是 CPU 使用率卻不一定很高。
由此可見,平均負載與 CPU 使用率有一定關(guān)聯(lián),但并沒有絕對的關(guān)系。
如何查看平均負載?
一般來說,我們可以通過 top? 和 uptime 命令來監(jiān)控服務器的平均負載。
在服務器命令行輸入 top 即可查看到當前系統(tǒng)的負載情況,如下圖所示。
上圖中平均負載的 3 個數(shù)值分別代表 1 分鐘、5 分鐘、15 分鐘系統(tǒng)的平均負載情況。通過這三個數(shù)值的變化,我們可以知道系統(tǒng)最近一段時間的壓力變化趨勢。例如:load average: 15.00, 10.75, 3.25 表示過去 1 分鐘負載為 15,過去 5 分鐘負載為 10.75,過去 15 分鐘負載為 3.25,可以看到其平均負載壓力是越來越大的。
top? 命令輸出的信息非常多,有時候會干擾我們的視野。所以如果你只需要看系統(tǒng)負載情況,那么你可以用 uptime 命令,如下圖所示。
-w438
uptime 命令只輸出了一行信息,非常簡潔。
如果你需要持續(xù)地查看平均負載的變化,那么可以用如下命令。該命令會會持續(xù)輸出最新的負載信息,并高亮變化的部分。
watch -d uptime
-w499
總結(jié)
本文首先介紹了 Linux 進程的 7 種狀態(tài),分別是:
- TASK_RUNNING 可執(zhí)行狀態(tài),縮寫 R。
- TASK_INTERRUPTIBLE 可中斷的睡眠狀態(tài),縮寫 S。
- TASK_UNINTERRUPTIBLE 不可中斷睡眠狀態(tài),縮寫 D。
- TASK_STOPPED 暫停狀態(tài)、TASK_TRACED 狀態(tài),縮寫 T。
- TASK_DEAD - EXIT_ZOMBIE 退出狀態(tài),縮寫 Z。
- TASK_DEAD - EXIT_DEAD 退出狀態(tài),縮寫 X。
隨后,我們介紹了平均負載指標的定義,即:單位時間內(nèi),系統(tǒng)中處于可運行狀態(tài)和不可中斷狀態(tài)的平均進程數(shù)。
接著,我們將其與 CPU 使用率做了對比,知道兩者的區(qū)別在于:平均負載不僅包括了正在使用 CPU 的進程,還包括等待 CPU 和等待 I/O 的進程。而 CPU 使用率指的是正在使用 CPU 的進程,由此可見它們兩者是不同的。
最后,我們介紹了查看平均負載指標的 2 個命令,即 top? 和 uptime? 命令。如果需要持續(xù)關(guān)注平均負載的變化,那么可以使用 watch -d uptime 命令持續(xù)輸出,并高亮變化的部分。
參考資料
從源碼角度分析!進程狀態(tài)?理解 Linux 進程?看云
(13 條消息) Linux 進程狀態(tài)解析 之 R、S、D、T、Z、X (主要有三個狀態(tài))_sdkdlwk 的博客 - CSDN 博客_進程 d 狀態(tài)
Linux 進程狀態(tài) (ps stat) 詳解 - 火星小編 - 博客園?