天天看點

性能基礎之了解Linux系統平均負載和CPU使用率

做為一個性能測試工程師,每當我們發現計算機變慢的時候,我們通常的标準姿勢就是執行 uptime 或 top 指令,來了解系統的負載情況。

比如像下面這樣,我在指令行裡輸入了 uptime 指令,系統會傳回一行資訊。

<code>appletekimbp:~ apple$ uptime</code>

<code>20:44  up 21 days,  6:41, 2 users, load averages: 2.85 2.33 2.91</code>

但我想問的是,各位同學知道以上每列輸出的含義嗎?

<code>20:44                  # 目前時間</code>

<code>up 21 days,  6:41     # 系統運作時間</code>

<code>2 users               # 正在登入使用者數</code>

<code># 系統的平均負載,分别是1分鐘、5分鐘、15分鐘内系統的平均負載</code>

<code>load averages: 2.85 2.33 2.91</code>

這行資訊的後半部分,顯示 "load average",它的意思是"系統的平均負載",裡面有三個數字,我們可以從中判斷系統負載是大還是小。

我猜一定會有同學會說,平均負載不就是機關時間的 CPU 使用率嗎?上面 2.85,就代表 CPU 使用率是 285%。其實不是這樣的。

CPU 負載值在 Linux 系統中表示正在運作,處于可運作狀态的平均作業數(讀取一組與流程執行線程對應的機器語言的程式指令),或者非常重要,休眠但不可中斷(不可交錯的休眠狀态))。也就是說,要計算 CPU 負載的值,隻考慮正在運作或等待配置設定 CPU 時間的程序。不考慮正常的休眠過程(休眠狀态),僵屍或停止的過程。

簡單來說,平均負載是指機關時間内,系統處于可運作狀态和不可中斷狀态的平均程序數,也就是平均活躍程序數,它和 CPU 使用率并沒有直接關系。

程序狀态代碼 R 正在運作或可運作(在運作隊列中) D 不間斷休眠(通常為IO) S 可中斷休眠(等待事件完成) Z 失效/僵屍,終止但未被其父 T 停止,由作業控制停止信号或因為它被追蹤 [...]
性能基礎之了解Linux系統平均負載和CPU使用率

這裡先解釋下,可運作狀态和不可中斷狀态。

可運作狀态的程序,指的是正在使用CPU或者正在等待CPU的程序,也就是我們常用 ps 指令看到處于 R 狀态(Running 或 Runnable)的程序。

不可中斷狀态的程序,指的是正處于核心态關鍵流程中的程序,并且這些流程是不可打斷的,比如常見是等待硬體裝置的 I/O 響應。也就是我們在Ps 指令看到的D狀态(Uninterruptible Sleep,也稱為 Disk Sleep)的程序。 比如,當一個程序向磁盤讀寫資料時,為了保證資料的一緻性,在得到磁盤回複前,它是不能被其他程序或者中斷打斷的,這個時間的程序就處于不可中斷狀态。如果此時的程序被打斷,就容易出現磁盤資料與程序資料不一緻的問題。 

是以,不可中斷狀态實際上是系統對程序和硬體裝置的一種保護機制。 

是以,我們可以簡單了解為,平均負載其實就是平均活躍程序數。平均活躍程序數,直覺上的了解就是機關時間内的活躍程序數。 既然平均的是是活躍程序數,那麼理想的是,每個CPU上都剛好運作着一個程序,這樣每個CPU都得到了充分利用。

以下是單核處理器計算機中不同負載值的含義:

0.00:沒有任何作業正在運作或等待 CPU 執行,即 CPU 完全空閑。是以,如果正在運作的程式(程序)需要執行任務,它會向 CPU 請求作業系統,并立即為該程序配置設定 CPU 時間,因為沒有其他程序在競争它。

0.50:沒有任何作業在等待,但 CPU 正在處理以前的作業,并且它正在以 50% 的容量進行處理。在這種情況下,作業系統還可以立即将 CPU 時間配置設定給其他程序,而無需将其置于保持狀态。

1.00:隊列中沒有作業,但 CPU 正在以 100% 的容量處理先前的作業,是以如果新程序請求 CPU 時間,則必須将其保留到另一個作業完成或目前 CPU 插槽時間(例如,CPU tick)到期,作業系統決定哪一個是下一個給定的程序優先級。

1.50:CPU 工作在其容量的 100%,15個工作中有5個請求CPU時間,即 33.33%,必須排隊等待其他人耗盡他們配置設定的時間。是以,一旦超過1.0 的門檻值,就可以說系統過載,因為它不能立即處理所請求的 100% 的工作。

那麼很顯然,"load average"的值越低,比如等于0.2或0.3,就說明伺服器的工作量越小,系統負載比較低。

上面還看太懂怎麼辦?沒事,我們來看一個簡單的類比例子。

先假設最簡單的情況,你的計算機隻有一個 CPU,所有的運算都必須由這個 CPU 來完成。

那麼,我們不妨把這個 CPU 想象成一座大橋,橋上隻有一根車道,所有車輛都必須從這根車道上通過。(很顯然,這座橋隻能單向通行。)

系統負載為 0,意味着大橋上一輛車也沒有。

性能基礎之了解Linux系統平均負載和CPU使用率

系統負載為 0.5,意味着大橋一半的路段有車。

性能基礎之了解Linux系統平均負載和CPU使用率

系統負載為 1.0,意味着大橋的所有路段都有車,也就是說大橋已經"滿"了。但是必須注意的是,直到此時大橋還是能順暢通行的。

性能基礎之了解Linux系統平均負載和CPU使用率

系統負載為 1.7,意味着車輛太多了,大橋已經被占滿了(100%),後面等着上橋的車輛為橋面車輛的 70%。以此類推,系統負載 2.0,意味着等待上橋的車輛與橋面的車輛一樣多;系統負載 3.0,意味着等待上橋的車輛是橋面車輛的 2 倍。總之,當系統負載大于 1,後面的車輛就必須等待了;系統負載越大,過橋就必須等得越久。

性能基礎之了解Linux系統平均負載和CPU使用率

CPU 的系統負載,基本上等同于上面的類比。大橋的通行能力,就是CPU 的最大工作量;橋梁上的車輛,就是一個個等待 CPU 處理的程序(process)。

如果CPU 每分鐘最多處理100個程序,那麼系統負載0.2,意味着CPU在這 1 分鐘裡隻處理 20 個程序;系統負載 1.0,意味着 CPU 在這 1 分鐘裡正好處理 100 個程序;系統負載 1.7,意味着除了 CPU 正在處理的100 個程序以外,還有 70 個程序正排隊等着CPU處理。

為了計算機順暢運作,系統負載最好不要超過 1.0,這樣就沒有程序需要等待了,所有程序都能第一時間得到處理。很顯然,1.0 是一個關鍵值,超過這個值,系統就不在最佳狀态了,你要動手幹預了。

在具有多個處理器或核心(多個邏輯 CPU)的系統中,CPU 負載值的含義取決于系統中存在的處理器數量。是以,具有4  個處理器的計算機在達到4.00的負載之前将不會以100%使用,是以在解釋由 top,htop 或正常運作時間等指令提供的3個負載值時,你必須要做的第一件事 就是将它們分開。系統中存在的邏輯CPU數量,并從中得出結論。

舉個例子,如果你的計算機裝了 2 個 CPU,會發生什麼情況呢? 2 個 CPU,意味着計算機的處理能力翻了一倍,能夠同時處理的程序數量也翻了一倍。 還是用大橋來類比,兩個 CPU 就意味着大橋有兩根車道了,通車能力翻倍了

性能基礎之了解Linux系統平均負載和CPU使用率

是以,2 個CPU表明系統負載可以達到 2.0,此時每個 CPU 都達到 100%的工作量。推廣開來,n 個 CPU 的計算機,可接受的系統負載最大為n.0。

晶片廠商往往在一個 CPU 内部,包含多個CPU核心,這被稱為多核CPU。

在系統負載方面,多核 CPU 與多 CPU 效果類似,是以考慮系統負載的時候,必須考慮這台計算機有幾個 CPU、每個 CPU 有幾個核心。然後,把系統負荷除以總的核心數,隻要每個核心的負荷不超過 1.0,就表明計算機正常運作。 怎麼知道PC有多少個 CPU 核心呢? 

如果我們觀察在給定時間間隔内通過 CPU 的不同程序,則使用率百分比将表示相對于 CPU 執行與每個程序相對應的指令的那個時間間隔的時間部分。但這種計算隻運作的程序,而不是那些正在等待,無論它們是在隊列(可運作狀态)還是休眠但不可中斷(例如在等待輸入/輸出操作的結束)被認為。 是以,這個名額可以讓我們了解哪些程序最大程度地擠壓 CPU,但是如果系統狀态過載或者未充分利用,則不能給出真實的系統狀态圖。

現實工作中,我們經常容易把平均負載和 CPU 使用率混淆,從上面我們知道平均負載是指機關時間内,處于可運作狀态和不可中斷狀态的程序數。是以,它不僅包括正在使用 CPU 的程序,還包括等待 CPU 和等待I/O 的程序。而 CPU使用率,從上面的解釋我們知道是機關時間内繁忙程度,跟平均負載并不一定完全對應。比如:

CPU 密集型程序,使用大量 CPU 會導緻平均負載升高,這時候兩者是一緻的。

I/O 密集型程序,等待 I/O 也會導緻平均負載升高,但 CPU 使用率不一定很高。

大量等待 CPU 的程序排程也會導緻平均負載很高,此時的 CPU 使用率也會比較高。

在本文反複強調了不間斷休眠狀态非常重要 (第一張圖中的D),因為有時你可以在計算機中找到非常高的負載值,然而不同的運作過程使用率相對較低。如果你不考慮這種狀态,你會發現情況莫名其妙,你将不知道如何處理它。當程序等待某個資源的釋放并且其執行不能被中斷時,例如當它等待不可中斷的 I/O 操作時,程序處于此狀态完成(并非所有都是不可中斷的)。通常,這種情況是由于磁盤故障,網絡檔案系統(如NFS故障)或大量使用非常慢的裝置(例如USB 1.0 Pendrive)而發生的。

在這種情況下,我們将不得不使用替代工具,如 iostat 或 iotop,它們将訓示哪些程序正在執行更多的 I/O 操作,以便我們可以殺死這些程序或為它們配置設定較少的優先級(nice指令)能夠為其他更關鍵的程序配置設定更多的CPU 時間。 

性能基礎之了解Linux系統平均負載和CPU使用率

系統過載并超過1.0的負載值有時不是問題,因為即使有一些延遲,CPU也會處理隊列中的作業,負載将再次降低到1.0以下的值。但是如果系統的持續負載值大于1,則意味着它無法吸收執行中的所有負載,是以其響應時間将增加,系統将變得緩慢且無響應。高于1的高值,尤其是最後5分鐘和15分鐘的負載平均值是一個明顯的症狀,要麼我們需要改進計算機的硬體,通過限制使用者可以對系統的使用來節省更少的資源,或者除以多個相似節點之間的負載。

是以,我們提出以下建議:

<code>&gt;=0.70</code>:沒有任何反應,但有必要監控 CPU 負載。如果在一段時間内保持這種狀态,就必須在事情變得更糟之前進行調查。

<code>&gt;=1.00</code>:存在問題,您必須找到并修複它,否則系統負載的主要高峰将導緻您的應用程式變慢或無響應。

<code>&gt;=3.00</code>:你的系統變得 非常慢。甚至很難從指令行操作它來試圖找出問題的原因,是以修複問題需要的時間比我們之前采取的行動要長。你冒的風險是系統會更飽和并且肯定會崩潰。

<code>&gt;=5.00</code>:你可能無法恢複系統。你可以等待奇迹自發降低負載,或者如果你知道發生了什麼并且可以負擔得起,你可以在控制台中啟動 <code>kill-9&lt;process_name&gt;</code> 之類的指令 ,并祈求它運作在某些時候,以減輕系統負荷并重新獲得其控制權。否則,你肯定别無選擇,隻能重新啟動計算機。

繼續閱讀