1. 程式人生 > 其它 >1. 常用的一些系統性能排查linux命令

1. 常用的一些系統性能排查linux命令

當系統存在短板時,就會對效能造成較大的負面影響,比如當 CPU 的負載特別高時,任務就會排隊,不能及時執行。而其中,CPU、記憶體、I/O 這三個系統元件,又往往容易成為瓶頸,所以接下來我會對這三方面分別進行講解。

一、CPU

首先介紹計算機中最重要的計算元件中央處理器 CPU,圍繞 CPU 一般我們可以:

  1. 通過 top 命令,來觀測 CPU 的效能;

  2. 通過負載,評估 CPU 任務執行的排隊情況;

  3. 通過 vmstat,看 CPU 的繁忙程度。

1.1 top命令--CPU效能

如下圖,當進入 top 命令後,按 1 鍵即可看到每核 CPU 的執行指標和詳細效能。

CPU 的使用有多個維度的指標,下面分別說明

us 使用者態所佔用的 CPU 百分比,即引用程式所耗費的 CPU;
sy 核心態所佔用的 CPU 百分比,需要配合 vmstat 命令,檢視上下文切換是否頻繁;
ni 高優先順序應用所佔用的 CPU 百分比;
wa 等待 I/O 裝置所佔用的 CPU 百分比,經常使用它來判斷 I/O 問題,過高輸入輸出裝置可能存在非常明顯的瓶頸;
hi 硬中斷所佔用的 CPU 百分比;
si 軟中斷所佔用的 CPU 百分比;
st 在平常的伺服器上這個值很少發生變動,因為它測量的是宿主機對虛擬機器的影響,即虛擬機器等待宿主機 CPU 的時間佔比,這在一些超賣的雲伺服器上,經常發生;
id 空閒 CPU 百分比。
一般地,我們比較關注空閒 CPU 的百分比,它可以從整體上體現 CPU 的利用情況。
那 load 為 1 代表的是啥?針對這個問題,誤解還是比較多的。

1.2 負載 —— CPU 任務排隊情況

如果我們評估 CPU 任務執行的排隊情況,那麼需要通過負載(load)來完成。除了 top 命令,使用 uptime 命令也能夠檢視負載情況,load 的效果是一樣的,分別顯示了最近 1min、5min、15min 的數值。

很多人看到 load 的值達到 1,就認為系統負載已經到了極限。這在單核的硬體上沒有問題,但在多核硬體上,這種描述就不完全正確,它還與 CPU 的個數有關。例如: 單核的負載達到 1,總 load 的值約為 1; 雙核的每核負載都達到 1,總 load 約為 2; 四核的每核負載都達到 1,總 load 約為 4。 所以,對於一個 load 到了 10,卻是 16 核的機器,你的系統還遠沒有達到負載極限。

1.3 vmstat —— CPU 繁忙程度

要看 CPU 的繁忙程度,可以通過 vmstat 命令,下圖是 vmstat 命令的一些輸出資訊。

比較關注的有下面幾列: b 如果系統有負載問題,就可以看一下 b 列(Uninterruptible Sleep),它的意思是等待 I/O,可能是讀盤或者寫盤動作比較多; si/so 顯示了交換分割槽的一些使用情況,交換分割槽對效能的影響比較大,需要格外關注; cs 每秒鐘上下文切換(Context Switch)的數量,如果上下文切換過於頻繁,就需要考慮是否是程序或者執行緒數開的過多。 每個程序上下文切換的具體數量,可以通過檢視記憶體對映檔案獲取,如下程式碼所示(voluntary_ctxt_switchesh和nonvoluntary_ctxt_switches):

[www@m23p83 ~]$ cat /proc/1306/sta
stack stat statm status
[www@m23p83 ~]$ cat /proc/1306/status
Name: java
State: S (sleeping)
Tgid: 1306
Pid: 1306
PPid: 1
TracerPid: 0
Uid: 507 507 507 507
Gid: 507 507 507 507
Utrace: 0
FDSize: 256
Groups: 507
VmPeak: 5814736 kB
VmSize: 5812064 kB
VmLck: 0 kB
VmHWM: 1699552 kB
VmRSS: 1698872 kB
VmData: 5661480 kB
VmStk: 88 kB
VmExe: 4 kB
VmLib: 16464 kB
VmPTE: 3732 kB
VmSwap: 0 kB
Threads: 75
SigQ: 0/127436
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 2000000181005ccd
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
Cpus_allowed: f
Cpus_allowed_list: 0-3
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 87
nonvoluntary_ctxt_switches: 4

二、記憶體

邏輯地址可以對映到兩個記憶體段上:實體記憶體和虛擬記憶體,那麼整個系統可用的記憶體就是兩者之和。比如你的實體記憶體是 4GB,分配了 8GB 的 SWAP 分割槽,那麼應用可用的總記憶體就是 12GB。

2.1 top命令

VIRT(virtual memory usage) 這裡是指虛擬記憶體,一般比較大,不用做過多關注;
RES(resident memory usage) 我們平常關注的是這一列的數值,它代表了程序實際佔用的記憶體,平常在做監控時,主要監控的也是這個數值;
SHR(shared memory) 指的是共享記憶體,比如可以複用的一些 so 檔案等。

top命令開啟後,按f鍵如下所示,按Enter退出:

Current Fields: AEHIOQTWKNMbcdfgjplrsuvyzX  for window 1:Def
Toggle fields via field letter, type any other key to return

* A: PID = Process Id 0x00100000 PF_USEDFPU (thru 2.4)
* E: USER = User Name
* H: PR = Priority
* I: NI = Nice value
* O: VIRT = Virtual Image (kb)
* Q: RES = Resident size (kb)
* T: SHR = Shared Mem size (kb)
* W: S = Process Status
* K: %CPU = CPU usage
* N: %MEM = Memory usage (RES)
* M: TIME+ = CPU Time, hundredths
b: PPID = Parent Process Pid
c: RUSER = Real user name
d: UID = User Id
f: GROUP = Group Name
g: TTY = Controlling Tty
j: P = Last used cpu (SMP)
p: SWAP = Swapped size (kb)
l: TIME = CPU Time
r: CODE = Code size (kb)
s: DATA = Data+Stack size (kb)
u: nFLT = Page Fault count
v: nDRT = Dirty Pages count
y: WCHAN = Sleeping in Function
z: Flags = Task Flags <sched.h>
* X: COMMAND = Command name/line

Flags field:
0x00000001 PF_ALIGNWARN
0x00000002 PF_STARTING
0x00000004 PF_EXITING
0x00000040 PF_FORKNOEXEC
0x00000100 PF_SUPERPRIV
0x00000200 PF_DUMPCORE
0x00000400 PF_SIGNALED
0x00000800 PF_MEMALLOC
0x00002000 PF_FREE_PAGES (2.5)
0x00008000 debug flag (2.5)
0x00024000 special threads (2.5)
0x001D0000 special states (2.5)

預設情況下僅顯示比較重要的 PID、USER、PR、NI、VIRT、RES、SHR、S、%CPU、%MEM、TIME+、COMMAND 列。可以通過下面的快捷鍵來更改顯示內容。

  1. 通過 f 鍵可以選擇顯示的內容。按 f 鍵之後會顯示列的列表,按 a-z 即可顯示或隱藏對應的列,最後按回車鍵確定。

  2. 按 o 鍵可以改變列的顯示順序。按小寫的 a-z 可以將相應的列向右移動,而大寫的 A-Z 可以將相應的列向左移動。最後按回車鍵確定。

  3. 按大寫的 F 或 O 鍵,然後按 a-z 可以將程序按照相應的列進行排序。而大寫的 R 鍵可以將當前的排序倒轉。

top 執行中可以通過 top 的內部命令對程序的顯示方式進行控制。內部命令如下: s – 改變畫面更新頻率 l – 關閉或開啟第一部分第一行 top 資訊的表示 t – 關閉或開啟第一部分第二行 Tasks 和第三行 Cpus 資訊的表示 m – 關閉或開啟第一部分第四行 Mem 和 第五行 Swap 資訊的表示 N – 以 PID 的大小的順序排列表示程序列表 P – 以 CPU 佔用率大小的順序排列程序列表 M – 以記憶體佔用率大小的順序排列程序列表 h – 顯示幫助 n – 設定在程序列表所顯示程序的數量 q – 退出 top s – 改變畫面更新週期

三、IO

I/O 裝置可能是計算機裡速度最慢的元件了,它指的不僅僅是硬碟,還包括外圍的所有裝置。那硬碟有多慢呢?我們不去探究不同裝置的實現細節,直接看它的寫入速度(資料未經過嚴格測試,來自網路,僅作參考,在此只為了說明問題)。

如上圖所示,可以看到普通磁碟的隨機寫與順序寫相差非常大,但順序寫與 CPU 記憶體依舊不在一個數量級上。

緩衝區依然是解決速度差異的唯一工具,但在極端情況下,比如斷電時,就產生了太多的不確定性,這時這些緩衝區,都容易丟。

3.1 iostat

最能體現 I/O 繁忙程度的,就是 top 命令和 vmstat 命令中的 wa%。如果你的應用寫了大量的日誌,I/O wait 就可能非常高。

檢視磁碟 I/O 的工具(iostat), 如下所示:

圖中的指標詳細介紹如下所示。 %util:我們非常關注這個數值,通常情況下,這個數字超過 80%,就證明 I/O 的負荷已經非常嚴重了。 Device:表示是哪塊硬碟,如果你有多塊磁碟,則會顯示多行。 avgqu-sz:平均請求佇列的長度,這和十字路口排隊的汽車也非常類似。顯然,這個值越小越好。 awai:響應時間包含了佇列時間服務時間,它有一個經驗值。通常情況下應該是小於 5ms 的,如果這個值超過了 10ms,則證明等待的時間過長了。 svctm:表示操作 I/O 的平均服務時間,這裡就是 AVG 的意思。svctm 和 await 是強相關的,如果它們比較接近,則表示 I/O 幾乎沒有等待,裝置的效能很好;但如果 await 比 svctm 的值高出很多,則證明 I/O 的佇列等待時間太長,進而系統上執行的應用程式將變慢。

3.2 零拷貝

硬碟上的資料,在發往網路之前,需要經過多次緩衝區的拷貝,以及使用者空間和核心空間的多次切換。如果能減少一些拷貝的過程,效率就能提升,所以零拷貝應運而生。 零拷貝是一種非常重要的效能優化手段,比如常見的 Kafka、Nginx 等,就使用了這種技術。我們來看一下有無零拷貝之間的區別。 (1)沒有采取零拷貝手段 如下圖所示,傳統方式中要想將一個檔案的內容通過 Socket 傳送出去,則需要經過以下步驟: 將檔案內容拷貝到核心空間; 將核心空間記憶體的內容,拷貝到使用者空間記憶體,比如 Java 應用讀取 zip 檔案; 使用者空間將內容寫入到核心空間的快取中; Socket 讀取核心快取中的內容,傳送出去。

(2)採取了零拷貝手段 零拷貝有多種模式,我們用 sendfile 來舉例。如下圖所示,在核心的支援下,零拷貝少了一個步驟,那就 是核心快取向用戶空間的拷貝,這樣既節省了記憶體,也節省了 CPU 的排程時間,讓效率更高。