天天看點

一文搞清楚Linux性能監控及定位

 linux性能定位思路:

一文搞清楚Linux性能監控及定位

簡介:

本文主要從以下四個次元名額,來講解Linux監控及性能問題定位

CPU 、Memory 、 IO 、Network

一、top指令解析

使用top指令檢視程序使用資源情況

一文搞清楚Linux性能監控及定位
top - 19:45:57 目前系統時間
50 days 系統已經運作了50天
1 user 目前登陸1個使用者
load average 系統負載,反應程序在CPU排隊情況,等于【正在運作的程序+等待CPU時間片段的程序+等待IO的程序】三個數值分别表示為過去1分鐘/5分鐘/15分鐘的負載平均值。正常值為小于CPU的顆粒數
Task: 96 total 總程序數
1 running 正在運作的程序數
95 sleeping 睡眠的程序數
0 stopped 停止的程序數
0 zombie 當機程序數(僵屍程序數)
%Cpu(s):
0.7 us 使用者程序消耗的cpu,一般小于70%/80%是正常的
1.0 sy 系統核心程序消耗的cpu(作業系統的底層資源是在核心完成的,比如讀寫磁盤。超過10%就很高了,可能是IO、中斷、上下文切換導緻的
0.0 ni 改變過優先級的程序占用CPU的百分比
98.3 id 空閑cpu百分比
0.0 wa 等待IO的程序所消耗的占CPU的百分比,直覺說就是 如果這個值很高 就代表 cpu使用率不高 但是io很繁忙,需要去查一下io
0.0 hi 硬體中斷所消耗的CPU占比(硬中斷 Hardware IRQ)
0.0 si 軟體中斷所消耗的CPU占比(軟中斷 Software Interrupts)
0.0 st 不需要關注
KiB Mem :
1883564 total 實體記憶體總量
554480 free 空閑記憶體總量
362208 used 使用的實體記憶體總量
966876 buff/cache 用作核心緩存的記憶體量
cache緩存 存的是最近一段時間記憶體頻繁從磁盤中讀取的熱點資料,為了避免頻繁從磁盤取熱點資料。如果記憶體不足時,cache緩存會變小,将記憶體讓出來
buff緩沖 記憶體不是實時把資料寫入磁盤中的,而是一批一批的資料寫到磁盤中。一批一批的資料就是 buffers
KiB Swap: 交換區記憶體,一小部分在記憶體,大部分在磁盤上。在磁盤上開辟了一塊空間,當作記憶體來使用。最終運作在磁盤上。記憶體的運作速度至少是磁盤運作速度的幾百倍。是以交換區的記憶體,運作速度非常慢。swap used值變高,說明實體記憶體不夠用,而且系統開始變慢。從功能上講,交換分區主要是在記憶體不夠用的時候,将部分記憶體上的資料交換到swap空間上,以便讓系統不會因記憶體不夠用而導緻oom或者更緻命的情況出現。
0 total 交換區總量
0 free 空閑交換區總量
0 used 使用的交換區總量
1325836 avail Mem 緩沖的交換區總量
程序資訊
PID 程序id
PR 優先級(值越低優先級越高)
NI nice值,負值表示高優先級,正值表示低優先級
VIRT 程序使用的虛拟記憶體總量,機關kb。VIRT=SWAP+RES
RES 程序使用的、未被換出的實體記憶體大小,機關kb。(隻需要觀察這個值)RES=CODE+DATA
SHR 共享記憶體大小,機關kb。這個值可能會比較大,因為可能是多個程序共享的。
S 程序狀态。D=不可中斷的睡眠狀态 R=運作 S=睡眠 T=跟蹤/停止 Z=僵屍程序
%CPU 上次更新到現在的CPU時間占用百分比
%MEM 程序使用的實體記憶體百分比
TIME+ 程序使用的CPU時間總計,機關1/100秒
COMMAND 指令名/指令行

%iowait 這個值的含義,不用去關注,直覺說就是 如果這個值很高 就代表 cpu使用率不高 但是io很繁忙。隻知道高了,就去查io問題就行了

%iowait 官方解釋

Percentage of time that the CPU or CPUs were idle during

which the system had an outstanding disk I/O request

%iowait 表示在一個采樣周期内有百分之幾的時間屬于以下情況:CPU空閑、并且有仍未完成的I/O請求。      

1.1top指令

預設進入top時,各程序是按照CPU的占用量來排序的

多核cpu情況下,在top基本視圖中,按鍵盤數字“1”可以監控每個邏輯CPU的狀況

檢視具體某個程序的資訊

top -p pid(程序id)

top -p 620

檢視某個程序下的線程資訊

輸入H,顯示所有線程的情況

top -p pid #隻看某個程序的資料

top -H -p pid #檢視某個程序的線程資料

top -H -p 30350

一文搞清楚Linux性能監控及定位

顯示完整指令

top -c

或者先輸入top指令,然後再按c,來切換顯示程序的完成指令

一文搞清楚Linux性能監控及定位

注意:

ctrl+z 退出top指令,但是top程序依然在

ctrl+c退出top指令,并殺死該程序。

輸入M,按記憶體使用率排序

輸入P,按cpu使用率來排序,預設也是cpu使用率排序

二、IO

2.0 io

讀寫

2.1 IO與cpu的關系

參考連結:

​​I/O會一直占用CPU嗎? - 知乎​​

IO所需要的CPU資源非常少。大部分工作是分派給DMA完成的。

2.2 IO整個流程:

CPU計算檔案位址 ——> 委派DMA讀取檔案 ——> DMA接管總線 ——> CPU的A程序阻塞,挂起——> CPU切換到B程序 ——> DMA讀完檔案後通知CPU(一個中斷異常)——> CPU切換回A程序操作檔案

IO裝置發送中斷,CPU收到中斷後,挂起目前的程序,然後進行中斷,處理完後,回到之前的程序

計算機硬體上使用DMA來通路磁盤等IO,也就是請求發出後,CPU就不再管了,直到DMA處理器完成任務,再通過中斷告訴CPU完成了。

是以,單獨的一個IO時間,對CPU的占用是很少的,阻塞了就更不會占用CPU了,因為程式都不繼續運作了,CPU時間交給其它線程和程序了。

雖然IO不會占用大量的CPU時間,但是非常頻繁的IO還是會非常浪費CPU時間的,是以面對大量IO的任務,有時候是需要算法來合并IO,或者通過cache來緩解IO壓力的。

2.3

檢視io的常用三個指令

iostat -x

pidstat -d

sar -d

三、load average(平均負載)

平均負載:

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

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

不可中斷狀态的程序則是正處于核心态關鍵流程中的程序,并且這些流程是不可打斷的,比如最常見的是等待硬體裝置的 I/O 響應,也就是我們在 ps 指令中看到的 D 狀态(Uninterruptible Sleep,也稱為 Disk Sleep)的程序

比如,當一個程序向磁盤讀寫資料時,為了保證資料的一緻性,在得到磁盤回複前,它是不能被其他程序或者中斷打斷的,這個時候的程序就處于不可中斷狀态。如果此時的程序被打斷了,就容易出現磁盤資料與程序資料不一緻的問題。

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

通俗一點講,負載就是正在使用/等待cpu的隊列 與 等待io的隊列之和。

負載的解讀:

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

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

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

一文搞清楚Linux性能監控及定位

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

一文搞清楚Linux性能監控及定位

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

一文搞清楚Linux性能監控及定位

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

一文搞清楚Linux性能監控及定位

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是一個關鍵值,超過這個值,系統就不在最佳狀态了,你要動手幹預了。

系統負荷的經驗法則

1.0是系統負荷的理想值嗎?

不一定,系統管理者往往會留一點餘地,當這個值達到0.7,就應當引起注意了。經驗法則是這樣的:

當系統負荷持續大于0.7(但 70% 這個數字并不是絕對的),你必須開始調查了,問題出在哪裡,防止情況惡化。

當系統負荷持續大于1.0,你必須動手尋找解決辦法,把這個值降下來。

當系統負荷達到5.0,就表明你的系統有很嚴重的問題,長時間沒有響應,或者接近當機了。你不應該讓系統達到這個值。

平均負載與cpu使用率

平均負載是指機關時間内,處于可運作狀态和不可中斷狀态的程序數。是以,它不僅包括了正在使用 CPU 的程序,還包括等待 CPU 和等待I/O 的程序, 而 CPU 使用率,是機關時間内 CPU 繁忙情況的統計,跟平均負載并不一定完全對應。比如:

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

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

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

多處理器情況

上面,我們假設你的電腦隻有1個CPU。如果你的電腦裝了2個CPU,會發生什麼情況呢?

2個CPU,意味着電腦的處理能力翻了一倍,能夠同時處理的程序數量也翻了一倍。

還是用大橋來類比,兩個CPU就意味着大橋有兩根車道了,通車能力翻倍了。

一文搞清楚Linux性能監控及定位

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

多核處理器情況

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

在系統負荷方面,多核CPU與多CPU效果類似,是以考慮系統負荷的時候,必須考慮這台電腦有幾個CPU、每個CPU有幾個核心。然後,把系統負荷除以總的核心數,隻要每個核心的負荷不超過1.0,就表明電腦正常運作。

怎麼知道電腦有多少個CPU核心呢?

"cat /proc/cpuinfo"指令,可以檢視CPU資訊。

"grep -c 'model name' /proc/cpuinfo"指令,直接傳回CPU的總核心數。

最佳觀察時長

最後一個問題,"load average"一共傳回三個平均值----1分鐘系統負荷、5分鐘系統負荷,15分鐘系統負荷,

三個不同時間間隔的平均值,其實給我們提供了,分析系統負載趨勢的資料來源,讓我們能更全面、更立體地了解目前的負載狀況

如果 1 分鐘、5 分鐘、15 分鐘的三個值基本相同,或者相差不大,那就說明系統負載很平穩。

但如果 1 分鐘的值遠小于 15 分鐘的值,就說明系統最近 1 分鐘的負載在減少,而過去15 分鐘内卻有很大的負載。

反過來,如果 1 分鐘的值遠大于 15 分鐘的值,就說明最近 1 分鐘的負載在增加,這種增加有可能隻是臨時性的,也有可能還會持續增加下去,是以就需要持續觀察。一旦 1分鐘的平均負載接近或超過了 CPU 的個數,就意味着系統正在發生過載的問題,這時就得分析調查是哪裡導緻的問題,并要想辦法優化了。

四、程序的各種狀态

就緒狀态(Running):

程序已經準備好,已配置設定到所需資源,隻要配置設定到CPU就能夠立即運作。

運作态和就緒态之間的轉換是由程序排程程式引起的,程序排程程式是作業系統的一部分。

就緒狀态不消耗cpu

運作狀态(Running):

程序處于就緒狀态被排程後,程序進入執行狀态

可中斷睡眠狀态:

正在運作的程序由于某些事件而暫時無法運作,程序受到阻塞。在條件滿足就會被喚醒(也可以提前被信号打斷喚醒),進入就緒狀态等待系統調用

一般都是等待事務,這個過程很長,不知道啥時候傳回結果。比如python中的input

不可中斷睡眠狀态(磁盤休眠狀态):

除了不會因為接收到信号而被喚醒運作之外,他與可中斷狀态相同。

等待資源,過程很快會傳回結果,毫秒級别,不用打斷。在滿足請求時進入就緒狀态等待系統調用。

在這個狀态的程序通常會等待IO的結束。

比如:

cpu是在記憶體裡運作的,資料缺失,會去磁盤裡取,讀取磁盤,等待資料磁盤從資料傳回,這個過程是就是不可中斷。

這個過程很快。

終止狀态/僵屍狀态(ZOMBIE):

該程序已經結束了,但是父程序還沒有使用wait()系統調用。因為父程序不能讀取到子程序退出的傳回代碼,是以就會産生僵死程序。為了父程序能夠獲知它的消息,子程序的程序描述符仍然被保留,一但父程序調用wait(),程序描述符就會被釋放。該程序無法再被執行

停止狀态:

程序停止執行,程序不能投入運作。通常這種狀态發生在接受到SIGSTOP、SIGTSTP、SIGTTIN、SIGOUT等信号(停止信号)的時候,正常停止。此外,在調試期間接受到的任何信号,都會使程序進入這種狀态。

使用top指令,檢視s列,為每個程序的狀态。

一文搞清楚Linux性能監控及定位

線程的就緒狀态與運作狀态,都是R(RUNNING)狀态。我們無法從R上區分目前程序到底是就緒還是正在運作。

程序與線程:

程序之間互相獨立,但同一程序下的各個線程之間共享程式的記憶體空間(包括代碼段、資料集、堆等)及一些程序級的資源(如打開檔案和信号),某程序内的線程在其它程序不可見;

五、CPU

cpu 相當于 工廠中的房間勞工,記憶體相當于工廠中的房間,磁盤相當于倉庫。cpu隻能在記憶體裡工作。

5.1 CPU數量&每顆實體CPU的核數

一個伺服器主機闆可以插多個CPU稱為多路,一個CPU可以有多個實體核。

如果開啟了超線程,一個實體核可以分成n個邏輯核(一般是2),n為超線程的數量。

總核數 = 實體CPU個數 * 每顆實體CPU的核數

總邏輯CPU數 = 實體CPU個數 X 每顆實體CPU的核數 X 超線程數

注:我們常說的幾核一般不包括邏輯核數。

檢視實體cpu數:主機闆上實際插入的cpu數量

cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l      

cpu核數:單塊CPU上面能處理資料的晶片組的數量,如雙核、四核等 (cpu cores)

cat /proc/cpuinfo| grep "cpu cores"| uniq      

 注:查的是每顆CPU的實體核數

邏輯cpu數:一般情況下,邏輯cpu=實體CPU個數×每顆核數,如果不相等的話,則表示伺服器的CPU支援超線程技術

檢視單顆CPU的邏輯核數

cat /proc/cpuinfo | grep “siblings” | uniq      

檢視所有CPU的邏輯核數

cat /proc/cpuinfo| grep "processor"| wc -l      
grep -c 'model name' /proc/cpuinfo      

檢視CPU資訊:

cat /proc/cpuinfo      

系統上隻有一個cpu,但是這個cpu的實體核是4。代表在一瞬間,有4個人在幹活。

使用top指令,觀察cpu。

一文搞清楚Linux性能監控及定位

 %Cpu(s),s說明是複數,存在多個cpu,我們按1,可以展開

一文搞清楚Linux性能監控及定位

 cpu0負責所有cpu核心的排程。

使用top指令,檢視cpu資料時,發現cpu0的使用率遠遠高于cpu1,可能導緻問題的原因

1、cpu排程有問題

2、某些應用程式

5.2 雲伺服器的cpu

我檢視了一下自己買的華為雲服務的cpu規格

一文搞清楚Linux性能監控及定位

 2vCPUs:

雲伺服器一般都是說幾核,如2核,其實就是vCPU,幾核就是幾個vCPU。如2核就是2vCPU,注意,這裡是2個虛拟cpu,并不是2個實體cpu。(1個實體cpu可以虛拟出多個vCPU)

5.3 CPU工作原理&CPU時間片

​​cpu 時間片消耗表|cpu消耗表 - 小林野夫 - 部落格園​​

 1秒=1000毫秒(ms)=1,000,000 微秒(μs)=1,000,000,000 納秒(ns)=1,000,000,000,000 皮秒(ps)

舉個例子:cpu 相當于一個 工廠中的房間勞工,将1秒鐘,分成10份,第一個1/10秒,做a事情,下一個1/10秒,做b事情,這樣輪流依次做不同的事情。

cpu時間片的大小通常為10~100ms,在 Windows 作業系統上,一個時間片通常在十幾毫秒(譯者注:預設 15.625ms)

時間片即CPU配置設定給各個程式的時間,每個程序被配置設定一個時間段,稱作它的時間片,即該程序允許運作的時間,使各個程式從表面上看是同時進行的。

如果在時間片結束時程序還在運作,則CPU将被剝奪并配置設定給另一個程序。如果程序在時間片結束前阻塞或結束,則CPU當即進行切換。而不會造成CPU資源浪費。

如果時間片為20ms,某個線程所需要的時間小于20ms,那麼不到20ms就會切換到其他線程;如果一個線程所需的時間超過20ms,系統也最多隻給20ms。

在宏觀上:我們可以同時打開多個應用程式,每個程式并行不悖,同時運作。

但在微觀上:由于隻有一個CPU,一次隻能處理程式要求的一部分,如何處理公平,一種方法就是引入時間片,每個程式輪流執行。

程序時間片:​​20ms​​

程序上下文切換:10ms

線程上下文切換 :3.8μs,這個分為同程序線程和非同程序線程他們時間不一樣

中斷上下文切換:很短

GC:對第0代執行一次垃圾回收時間不超過1ms

固态硬碟通路10-100us

機械硬碟通路1-10ms

5.4 CPU各種名額

us:使用者程序消耗的cpu

sy:系統核心程序消耗的cpu

哪些行為消耗us:

程序在執行業務邏輯的時候,消耗cpu,屬于us。

當us消耗過高時,我們需要關注哪些使用者程序導緻了us過高。

哪些行為消耗sy:

系統寫日志,對cpu的消耗,屬于sy。

程序的上下文切換,對cpu的消耗,屬于sy。

作業系統的底層資源是在核心完成的,比如讀寫磁盤。

超過10%就很高了,可能是IO、中斷、上下文切換導緻的。需要檢視wa與si。

wa高,則是io導緻的,si高則是上下文切換、中斷導緻的。

 5.4.3NI&PR

ni,使用者程序空間内改變過優先級的程序占用CPU百分比

一文搞清楚Linux性能監控及定位

 兩列:PR(priority)程序​​優先級​​和 NI(nice)優先級切換等級

PR 列的值是:rt 或大于等于 0 的數字;NI 列的值是:[-20, 19]之間的數字

NI -- Nice Value

這項任務的優先價值。負的nice值意味着更高的優先級,而正的nice值意味着更低的優先級。

該字段中的0表示在确定任務的排程能力時不會調整優先級。

PR -- Priority 優先事項

任務的排程優先級。如果在該字段中看到“rt”,則表示任務正在實時排程優先級下運作。

任務清單數量很多,一般都超過了 CPU 的數量,超過了 CPU 的數量的程序,都要使用 CPU,就要排隊,排隊,有 3 種隊列:Deadline 最後期限隊列 dl_rq,實時任務隊列 rt_rq,cfs 公平隊列 cfs_rq. 每種隊列中排隊的任務比較多,事情就會比較複雜,是以需要有預設的、大家都遵循的‘優先級’,和出現緊急情況,能靈活調整的‘排程政策’。

六、硬碟

資料最終的存貯,在硬碟。如mysql的資料,存在硬碟裡。但是系統存取硬碟資料的速度比較慢,在記憶體裡存取資料比較快。

在性能方面,固态硬碟讀寫速度是遠遠超過機械硬碟的。

固态硬碟通路10-100us

機械硬碟通路1-10ms

七、記憶體

把硬碟裡的資料,取出來,放到記憶體裡,然後cpu在記憶體裡對資料進行加工。

新生成的資料,也是在記憶體裡生成,然後同步到磁盤裡。

記憶體往磁盤裡同步資料,不是實時進行的。比如日常工作過程中,使用電腦編輯文檔,沒有做儲存,電腦斷電重新開機後,發現文檔裡的内容丢失了。因為這些資料在記憶體裡,并沒有同步到磁盤裡。

1、記憶體是什麼?

1)記憶體又稱主存,是 CPU 能直接尋址的存儲空間,由半導體器件制成

2)記憶體的特點是存取速率快

2、記憶體的作用

  • 1)暫時存放 cpu 的運算資料
  • 2)硬碟等外部存儲器交換的資料
  • 3)保障 cpu 計算的穩定性和高性能

記憶體頁:

一塊記憶體的大小,一般一頁時4kb(可以自己調),mysql裡,一塊記憶體快時16kb。取一頁資料,就是取出16kb的資料。

如果一頁記憶體時,資料不在記憶體時,這是會産生缺頁異常,但不是真的異常,隻是因為記憶體裡缺少資料,這是需要去磁盤讀取資料,放到記憶體裡,此時缺頁異常就恢複了。

使用top指令檢視記憶體

Mem 實體記憶體、swap 記憶體

一文搞清楚Linux性能監控及定位

KiB Swap 記憶體:

交換區記憶體,一小部分在記憶體,大部分在磁盤上。在磁盤上開辟了一塊空間,當作記憶體來使用。最終運作在磁盤上。記憶體的運作速度至少是磁盤運作速度的幾百倍。是以交換區的記憶體,運作速度非常慢。swap used值變高,說明實體記憶體不夠用,而且系統開始變慢。從功能上講,交換分區主要是在記憶體不夠用的時候,将部分記憶體上的資料交換到swap空間上,以便讓系統不會因記憶體不夠用而導緻oom或者更緻命的情況出現。

一文搞清楚Linux性能監控及定位

 分析Mem 實體記憶體:

檢視total總量、free空閑、used使用的記憶體。

分析swap 記憶體:

看有沒有在使用swap記憶體,不看total,看used,不是看used被使用,而是觀察used的使用量,往上升,才代表swap記憶體被使用。當使用swap記憶體時,系統運作速度會變慢。

Mem實體記憶體free的值不會為0.

系統都有保護措施,如果記憶體徹底為0了,那麼系統連shutup、teardown 關機 重新開機這些指令都不能執行。是以,系統設定了一個保護值,這個值在幾十M左右。是以free這個值,不會為0。

什麼時候記憶體就不足了?

java應用程式,除了記憶體溢出會導緻記憶體不足,其他的比如記憶體4g,用了3個g,這不是記憶體不足。java應用程式記憶體不足,隻有一個表現,就是程式報記憶體溢出了,其他都不是記憶體不足。因為java程式是先申請記憶體,java程序啟動時,會申請配置設定很大的記憶體,記憶體使用率肯定很高。

如果其他的程式,非預申請程式。記憶體使用率不要超過85%。

buffers/cache

一文搞清楚Linux性能監控及定位

cache 緩存:

緩存的是最近一段時間頻繁從磁盤裡取的檔案(熱點資料),緩存也是在記憶體裡。

這些熱點資料,用完之後并沒有丢棄,而是緩存在了記憶體裡,為了避免頻繁的從磁盤裡互動資料。

當記憶體緊張時,緩存資料會變小。

buffers緩沖:

向磁盤裡寫的資料。

使用top指令,檢視程序的列資訊。

一文搞清楚Linux性能監控及定位

 隻需要關注RES就可以了,RES表示該程序占用的實體記憶體。(SHR是共享記憶體,VITR=SHR+虛拟記憶體)

八、中斷

中斷概念:

中斷是指在CPU正常運作期間,由于内外部事件或由程式預先安排的事件引起的 CPU 暫時停止正在運作的程式,轉而為該内部或外部事件或預先安排的事件服務的程式中去,服務完畢後再傳回去繼續運作被暫時中斷的程式。

Linux中通常分為硬中斷(Hardware IRQ)和軟中斷(Software Interrupts)

(1) 硬中斷

由與系統相連的外設(比如網卡、硬碟)自動産生的。主要是用來通知作業系統系統外設狀态的變化。比如當網卡收到資料包

的時候,就會發出一個中斷。我們通常所說的中斷指的是硬中斷(hardirq)。

(2) 軟中斷

為了滿足實時系統的要求,中斷處理應該是越快越好。linux為了實作這個特點,當中斷發生的時候,硬中斷處理那些短時間

就可以完成的工作,而将那些處理事件比較長的工作,放到中斷之後來完成,也就是軟中斷(softirq)來完成。

導緻軟中斷的情況:

主動中斷:在時間片内cpu完成了任務,主動讓出cpu

被動中斷:在時間片内,cpu沒有完成任務,被動讓出cpu

使用者程序主動發起中斷

大量中斷導緻系統上下文切換,會消耗核心cpu(系統cpu)

九、上下文切換

參考部落格:

在每個任務運作前,CPU 都需要知道任務從哪裡加載、又從哪裡開始運作,也就是說,需要系統事先幫它設定好 CPU 寄存器和程式計數器

CPU 寄存器,是 CPU 内置的容量小、但速度極快的記憶體。而程式計數器,則是用來存儲CPU 正在執行的指令位置、或者即将執行的下一條指令位置。它們都是 CPU 在運作任何任務前,必須的依賴環境,是以也被叫做 CPU 上下文

CPU 上下文切換,就是先把前一個任務的 CPU 上下文(也就是 CPU 寄存器和程式計數器)儲存起來,然後加載新任務的上下文到這些寄存器和程式計數器,最後再跳轉到程式計數器所指的新位置,運作新任務。

3種上下文切換情況:

根據任務的不同,CPU 的上下文切換就可以分為幾個不同的場景,也就是程序上下文切換、線程上下文切換以及中斷上下文切換。

程序核心空間/使用者空間切換導緻CPU上下文切換

Linux 按照特權等級,把程序的運作空間分為核心空間和使用者空間,CPU 特權等級的 Ring 0 和 Ring 3。程序既可以在使用者空間運作,又可以在核心空間中運作。

程序在使用者空間運作時,被稱為程序的使用者态,而陷入核心空間的時候,被稱為程序的核心态。

從使用者态到核心态的轉變,需要通過系統調用來完成。

比如,當我們檢視檔案内容時,就需要多次系統調用來完成:首先調用 open() 打開檔案,然後調用 read() 讀取檔案内容,并調用 write() 将内容寫到标準輸出,最後再調用 close() 關閉檔案。

核心空間(Ring 0)具有最高權限,可以直接通路所有資源;

使用者空間(Ring 3)隻能通路受限資源,不能直接通路記憶體等硬體裝置,必須通過系統調用陷入到核心中,才能通路這些特權資源。

系統調用(程序核心空間/使用者空間切換)的過程發生 CPU 上下文切換

CPU 寄存器裡原來使用者态的指令位置,需要先儲存起來。

接着,為了執行核心态代碼,CPU 寄存器需要更新為核心态指令的新位置。

最後才是跳轉到核心态運作核心任務 。

而系統調用結束後,CPU 寄存器需要恢複原來儲存的使用者态,然後再切換到使用者空間,繼續運作程序。

是以,一次系統調用的過程,其實是發生了兩次 CPU 上下文切換。

系統調用過程中,并不會涉及到虛拟記憶體等程序使用者态的資源,也不會切換程序。這跟我們通常所說的程序上下文切換是不一樣的:

程序上下文切換,是指從一個程序切換到另一個程序運作。

而系統調用過程中一直是同一個程序在運作

程序上下文切換

程序是由核心來管理和排程的,程序的切換隻能發生在核心态。

是以,程序的上下文不僅包括了虛拟記憶體、棧、全局變量等使用者空間的資源,還包括了核心堆棧、寄存器等核心空間的狀态。

是以,程序的上下文切換就比系統調用時多了一步:

在儲存目前程序的核心狀态和 CPU 寄存器之前,需要先把該程序的虛拟記憶體、棧等儲存下來;

而加載了下一程序的核心态後,還需要重新整理程序的虛拟記憶體和使用者棧。

如下圖所示,儲存上下文和恢複上下文的過程并不是“免費”的,需要核心在 CPU 上運作才能完成。

一文搞清楚Linux性能監控及定位

每次上下文切換都需要幾十納秒到數微秒的 CPU 時間。

這個時間還是相當可觀的,特别是在程序上下文切換次數較多的情況下,很容易導緻 CPU 将大量時間耗費在寄存器、核心棧以及虛拟記憶體等資源的儲存和恢複上,進而大大縮短了真正運作程序的時間。

大量的上下文切換會消耗我們的cpu,導緻平均負載升高。

程序切換時才需要切換上下文,換句話說,隻有在程序排程的時候,才需要切換上下文。

Linux 為每個 CPU 都維護了一個就緒隊列,将活躍程序(即正在運作和正在等待CPU 的程序)按照優先級和等待 CPU 的時間排序,然後選擇最需要 CPU 的程序,也就是優先級最高和等待 CPU 時間最長的程序來運作。

程序在什麼時候才會被排程到cpu上運作:

場景一:

就是一個程序執行完終止了,它之前使用的 CPU 會釋放出來,這個時候再從就緒隊列裡,拿一個新的程序過來運作。

場景二:

為了保證所有程序可以得到公平排程,CPU 時間被劃分為一段段的時間片,這些時間片再被輪流配置設定給各個程序。

這樣,當某個程序的時間片耗盡了,就會被系統挂起,切換到其它正在等待 CPU 的程序運作。

場景三:

程序在系統資源不足(比如記憶體不足)時,要等到資源滿足後才可以運作,這個時候程序也會被挂起,并由系統排程其他程序運作。

場景四:

當程序通過睡眠函數 sleep 這樣的方法将自己主動挂起時,自然也會重新排程。

場景五:

當有優先級更高的程序運作時,為了保證高優先級程序的運作,目前程序會被挂起,由高優先級程序來運作。

場景六:

發生硬體中斷時,CPU 上的程序會被中斷挂起,轉而執行核心中的中斷服務程式。

線程上下文切換

線程與程序最大的差別在于,線程是排程的基本機關,而程序則是資源擁有的基本機關。

所謂核心中的任務排程,實際上的排程對象是線程;而程序隻是給線程提供了虛拟記憶體、全局變量等資源。

可以這麼了解線程和程序:

當程序隻有一個線程時,可以認為程序就等于線程。

當程序擁有多個線程時,這些線程會共享相同的虛拟記憶體和全局變量等資源。這些資源在上下文切換時是不需要修改的。

另外,線程也有自己的私有資料,比如棧和寄存器等,這些在上下文切換時也是需要儲存的。

線程的上下文切換其實就可以分為兩種情況:

第一種,前後兩個線程屬于不同程序。此時,因為資源不共享,是以切換過程就跟程序上下文切換是一樣。

第二種,前後兩個線程屬于同一個程序。此時,因為虛拟記憶體是共享的,是以在切換時,虛拟記憶體這些資源就保持不動,隻需要切換線程的私有資料、寄存器等不共享的資料

同程序内的線程切換,要比多程序間的切換消耗更少的資源,而這,也正是多線程代替多程序的一個優勢

中斷上下文切換

為了快速響應硬體的事件,中斷處理會打斷程序的正常排程和執行,轉而調用中斷處理程式,響應裝置事件。而在打斷其他程序時,就需要将程序目前的狀态儲存下來,這樣在中斷結束後,程序仍然可以從原來的狀态恢複運作。

跟程序上下文不同,中斷上下文切換并不涉及到程序的使用者态。是以,即便中斷過程打斷了一個正處在使用者态的程序,也不需要儲存和恢複這個程序的虛拟記憶體、全局變量等使用者态資源。

中斷上下文,其實隻包括核心态中斷服務程式執行所必需的狀态,包括 CPU 寄存器、核心堆棧、硬體中斷參數等。對同一個 CPU 來說,中斷處理比程序擁有更高的優先級,是以中斷上下文切換并不會與程序上下文切換同時發生。同樣道理,由于中斷會打斷正常程序的排程和執行,是以大部分中斷處理程式都短小精悍,以便盡可能快的執行結束。另外,跟程序上下文切換一樣,中斷上下文切換也需要消耗 CPU,切換次數過多也會耗費大量的 CPU,甚至嚴重降低系統的整體性能。是以,當你發現中斷次數過多時,就需要注意去排查它是否會給你的系統帶來嚴重的性能問題

十、vmstat介紹

vmstat可以對作業系統的記憶體資訊、程序狀态、 CPU活動、磁盤等資訊進行監控,不足之處是無法 對某個程序進行深入分析。

vmstat

vmstat [-a] [-n] [-S unit] [delay [ count]]
-a:顯示活躍和非活躍記憶體
-m:顯示slabinfo
-n:隻在開始時顯示一次各字段名稱。
-s:顯示記憶體相關統計資訊及多種系統活動數量。
delay:重新整理時間間隔。如果不指定,隻顯示一條結果。
count:重新整理次數。如果不指定重新整理次數,但指定了重新整理時間間隔,這 時重新整理次數為無窮。
-d:顯示各個磁盤相關統計資訊。
-S:使用指定機關顯示。參數有 k 、K 、m 、M ,分别代表1000、
1024、1000000、1048576位元組(byte)。預設機關為K(1024 bytes)
-V:顯示vmstat版本資訊。
-p:顯示指定磁盤分區統計資訊
-D:顯示磁盤總體資訊      

一般用法

  • delay:重新整理時間間隔。如果不指定,隻顯示一條結果。
  • count:重新整理次數。如果不指定重新整理次數,但指定了重新整理時間間隔,這 時重新整理次數為無窮。

vmstat 10

10秒重新整理一次結果,隻要不停止,會持續顯示重新整理後的資料

一文搞清楚Linux性能監控及定位

vmstat 10 5

10秒重新整理一次結果,一共顯示5次資料

一文搞清楚Linux性能監控及定位

 字段說明

procs
R列

R清單示運作和等待CPU時間片的程序數,這個值如果長期大于系統CPU個數,

說明CPU不足,需要增加CPU

B列 B清單示在等待資源的程序數,比如正在等待I/O或者記憶體交換等
memory
swpd列 swpd清單示切換到記憶體交換區的記憶體大小(機關KB),通俗講就是虛拟記憶體的 大小。如果swap值不為0或者比較大,隻要si、so的值長期為0.這種情況一般屬 于正常情況。
free列 free清單示目前空閑的實體記憶體(機關KB)
Buff列

Buff清單示baffers cached記憶體大小,也就是緩沖大小,一般對塊裝置的讀寫

才需要緩沖。

Cache列 Cache清單示page cached的記憶體大小,也就是緩存大小,一般作為檔案系統進 行緩沖,頻繁通路的檔案都會被緩存,如果cache值非常大說明緩存檔案比較多, 如果此時io中的bi比較小,說明檔案系統效率比較好。
swap
Si列 Si清單示由磁盤調入記憶體,也就是記憶體進入記憶體交換區的記憶體大小。
so列

so清單示由記憶體進入磁盤,也就是有記憶體交換區進入記憶體的記憶體大小。

一般情況下,si、so的值都為0,如果si、so的值長期不為0,則說明系統記憶體不 足,需要增加系統記憶體。

io
bi列 bi清單示由塊裝置讀入資料的總量,即讀磁盤,機關kb/s。
bo列 bo清單示寫到塊裝置資料的總量,即寫磁盤,機關kb/s
備注 如果bi+bo值過大,且wa值較大,則表示系統磁盤IO瓶頸。
system
in列 in列(interrupt)表示某一時間間隔内觀測到的每秒裝置中斷數
cs列 cs清單示每秒産生的上下文切換次數。(6位數以上才算不正常)
備注 這2個值越大,則由核心消耗的CPU就越多
cpu 
us列

us清單示使用者程序消耗的CPU時間百分比,us值越高,說明使用者程序消耗cpu時

間越多,如果長期大于50%,則需要考慮優化程式或者算法。

sy列 sy清單示系統核心程序消耗的CPU時間百分比,一般來說us+sy應該小于80%, 如果大于80%,說明可能出現CPU瓶頸。
id列 id清單示CPU處在空閑狀态的時間百分比
wa列 wa清單示等待所占的CPU時間百分比,wa值越高,說明I/O等待越嚴重,根據經 驗wa的參考值為20%,如果超過20%,說明I/O等待嚴重,引起I/O等待的原因可能 是磁盤大量随機讀寫造成的,也可能是磁盤或者此監控器的帶寬瓶頸(主要是塊 操作)造成的。
備注 如果評估CPU,需要重點關注procs項的r列值和CPU項的us、sy、wa列 的值。

R列+B列 就是我們理論上的負載

檢視系統上下文切換情況

使用 vmstat 這個工具,來查詢系統的上下文切換情況 ,主要關注以下幾項。

一文搞清楚Linux性能監控及定位

主要關注以下四個資料:

system
cs(context switch) 是每秒上下文切換的次數
in(interrupt) 則是每秒中斷的次數。
rocs
r(Running or Runnable) 是就緒隊列的長度,也就是正在運作和等待 CPU 的程序數。
b(Blocked) 則是處于不可中斷睡眠狀态的程序數

十一、pidstat工具介紹

pidstat 是sysstat 工具下的一個指令

安裝:

yum install -y sysstat

用法

用法: pidstat [ 選項 ] [ [ ] ]

Options are:

[ -d ] [ -h ] [ -I ] [ -l ] [ -R ] [ -r ] [ -s ] [ -t ] [ -U [ ] ]

[ -u ] [ -V ] [ -v ] [ -w ] [ -C ] [ -G ] [ --human ]

[ -p { [,...] | SELF | ALL } ] [ -T { TASK | CHILD | ALL } ]

常用參數

  • -u:預設的參數,顯示各個程序的cpu使用統計
  • -r:顯示各個程序的記憶體使用統計
  • -d:顯示各個程序的IO使用情況
  • -p:指定程序号
  • -w:顯示每個程序的上下文切換情況
  • -t:顯示選擇任務的線程的統計資訊外的額外資訊

所有程序cpu的使用情況

pidstat      

說明:

  • PID:程序ID
  • %usr:程序在使用者空間占用cpu的百分比
  • %system:程序在核心空間占用cpu的百分比
  • %guest:程序在虛拟機占用cpu的百分比
  • %CPU:程序占用cpu的百分比
  • CPU:處理程序的cpu編号(可以檢視目前程序在哪個cpu上運作)
  • %wait:
  • Command:目前程序對應的指令

檢視記憶體使用情況

pidstat -r -p 2818 1 4

pid為2818的程序,四秒鐘的記憶體使用情況,每秒展示一次,展示四次

也可以直接pidstat -r,是全部程序的記憶體使用情況

[root@iz2ze2w3v37sit3vf71kuez ~]# pidstat -r -p 2818 1 4
Linux 3.10.0-514.26.2.el7.x86_64 (iz2ze2w3v37sit3vf71kuez)  2021年08月13日   _x86_64_  (1 CPU)

20時22分32秒   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
20時22分33秒     0      2818      0.00      0.00   95252    3824   0.20  sysbench
20時22分34秒     0      2818      0.00      0.00   95252    3824   0.20  sysbench
20時22分35秒     0      2818      0.00      0.00   95252    3824   0.20  sysbench
20時22分36秒     0      2818      0.00      0.00   95252    3824   0.20  sysbench
平均時間:     0      2818      0.00      0.00   95252    3824   0.20  sysbench      

說明:

PID:程序辨別符
Minflt/s:任務每秒發生的次要錯誤,不需要從磁盤中加載頁
Majflt/s:任務每秒發生的主要錯誤,需要從磁盤中加載頁
VSZ:虛拟位址大小,虛拟記憶體的使用KB
RSS:常駐集合大小,非交換區記憶體使用KB
Command:task指令名      

11.1檢視各個程序IO使用情況

指令

pidstat -d

[root@iz2ze2w3v37sit3vf71kuez ~]# pidstat -d
Linux 3.10.0-514.26.2.el7.x86_64 (iz2ze2w3v37sit3vf71kuez)  2021年08月14日   _x86_64_  (1 CPU)

07時48分00秒   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
07時48分00秒     0         1      0.73      2.25      0.08     433  systemd
07時48分00秒     0        25      0.00      0.00      0.00      54  kswapd0
07時48分00秒     0        27      0.00      0.00      0.00       0  khugepaged
07時48分00秒     0       215      0.00      0.00      0.00    3937  kworker/u4:2
07時48分00秒     0       258      0.00      0.60      0.00   56303  jbd2/vda1-8
07時48分00秒     0       326      0.05      0.26      0.00    2760  systemd-journal
07時48分00秒     0       350      0.00      0.00      0.00      47  systemd-udevd
07時48分00秒     0       420      0.00      0.02      0.00     413  auditd      

字段說明

  • PID:程序id
  • kB_rd/s:每秒從磁盤讀取的KB
  • kB_wr/s:每秒寫入磁盤KB
  • kB_ccwr/s:任務取消的寫入磁盤的KB。當任務截斷髒的pagecache的時候會發生。
  • COMMAND:task的指令名
  • iodelay: IO的延遲時間

IO延遲是指控制器将IO指令發出後,到IO完成的過程中所消耗的時間。

pidstat -d 檢視哪個程序的IO有問題,主要檢視iodelay(io的延遲時間),一般小于1(機關ms)。

如果持續大于10,說明磁盤有瓶頸。

11.2 檢視每個程序上下文切換的詳細情況

指令

pidstat -w

隻檢視程序的上下文切換情況

pidstat -w 5      

5:間隔5秒,抓取一下資料

pidstat -w 5 2      

5:間隔5秒,抓取一下資料

2:移動抓取2次。

一文搞清楚Linux性能監控及定位

字段說明

  • cswch ,表示每秒主動任務上下文切換(voluntary context switches)的次數
  • nvcswch ,表示每秒被動任務上下文切換的(non voluntary context switches)次數

所謂主動上下文切換,是指程序無法擷取所需資源,導緻的上下文切換。比如說,

I/O、記憶體等系統資源不足時,就會發生主動上下文切換。

而被動上下文切換,則是指程序由于時間片已到等原因,被系統強制排程,進而發生

的上下文切換。比如說,大量程序都在争搶 CPU 時,就容易發生被動上下文切換。

pidstat -wt

檢視程序及線程的上下文切換情況

一文搞清楚Linux性能監控及定位

注意:

pidstat -w 5 2      

pidstat -wt 5 2      

-w是隻檢視程序上下文切換,-wt檢視程序及線程的上下文切換情況。

一文搞清楚Linux性能監控及定位

 如上圖,java是單程序多線程,檢視一個java程序,這個程序的上下文切換為0,但是線程是有上下文切換資料的。

是以我們在檢視上下文切換的資料時,既要檢視程序的,也要檢視線程的。

11.3 檢視特定程序的線程統計情況

指令

pidstat -t -p 3214

或者

pidstat -p 3214 -t

[root@iz2ze2w3v37sit3vf71kuez ~]# pidstat -t -p 3214 2
Linux 3.10.0-514.26.2.el7.x86_64 (iz2ze2w3v37sit3vf71kuez)  2021年08月14日   _x86_64_  (1 CPU)

08時12分02秒   UID      TGID       TID    %usr %system  %guest   %wait    %CPU   CPU  Command
08時12分04秒     0      3214         -    7.54   92.46    0.00    0.00  100.00     0  sysbench
08時12分04秒     0         -      3214    0.00    0.00    0.00    0.00    0.00     0  |__sysbench
08時12分04秒     0         -      3215    0.00    5.03    0.00   36.68    5.03     0  |__sysbench
08時12分04秒     0         -      3216    0.50    4.02    0.00   32.66    4.52     0  |__sysbench
08時12分04秒     0         -      3217    0.50    4.52    0.00   40.70    5.03     0  |__sysbench
08時12分04秒     0         -      3218    0.00    4.52    0.00   36.18    4.52     0  |__sysbench
08時12分04秒     0         -      3219    0.00    4.52    0.00   32.16    4.52     0  |__sysbench
08時12分04秒     0         -      3220    0.50    4.52    0.00   17.59    5.03     0  |__sysbench
08時12分04秒     0         -      3221    0.50    5.03    0.00   38.69    5.53     0  |__sysbench
08時12分04秒     0         -      3222    0.50    5.03    0.00   32.16    5.53     0  |__sysbench
08時12分04秒     0         -      3223    0.00    4.52    0.00   38.19    4.52     0  |__sysbench
08時12分04秒     0         -      3224    0.50    4.52    0.00   46.23    5.03     0  |__sysbench
08時12分04秒     0         -      3225    0.50    5.03    0.00   48.24    5.53     0  |__sysbench
08時12分04秒     0         -      3226    0.50    5.03    0.00   39.20    5.53     0  |__sysbench
08時12分04秒     0         -      3227    0.50    4.52    0.00   35.18    5.03     0  |__sysbench
08時12分04秒     0         -      3228    0.00    4.52    0.00   36.68    4.52     0  |__sysbench
08時12分04秒     0         -      3229    0.00    5.03    0.00   37.69    5.03     0  |__sysbench
08時12分04秒     0         -      3230    0.50    4.52    0.00   43.72    5.03     0  |__sysbench
08時12分04秒     0         -      3231    0.50    4.52    0.00   35.18    5.03     0  |__sysbench
08時12分04秒     0         -      3232    0.50    4.52    0.00   47.74    5.03     0  |__sysbench
08時12分04秒     0         -      3233    0.50    5.03    0.00   45.73    5.53     0  |__sysbench
08時12分04秒     0         -      3234    0.50    4.52    0.00   43.22    5.03     0  |__sysbench      

 說明:

TGID:  主線程的表示
TID:  線程id
%usr:  程序/線程在使用者空間占用cpu的百分比
%system: 程序/線程在核心空間占用cpu的百分比
%guest: 程序/線程在虛拟機占用cpu的百分比
%CPU: 程序/線程占用cpu的百分比
CPU: 處理/線程程序的cpu編号
Command: 目前程序對應的指令      

備注:

以上的幾項,程序的資料是所有線程的資料之和

十二、iostat

檢視部落格:

​​https://www.jianshu.com/p/5fed8be1b6e8​​

概述

iostat 主要用于輸出磁盤IO 和 CPU的統計資訊。

iostat屬于sysstat軟體包。可以用yum install sysstat 直接安裝。

iostat 用法

用法:iostat [選項] [<時間間隔>] [<次數>]

一文搞清楚Linux性能監控及定位

指令參數:

-c: 顯示CPU使用情況

-d: 顯示磁盤使用情況

-N: 顯示磁盤陣列(LVM) 資訊

-n: 顯示NFS 使用情況

-k: 以 KB 為機關顯示

-m: 以 M 為機關顯示

-t: 報告每秒向終端讀取和寫入的字元數和CPU的資訊

-V: 顯示版本資訊

-x: 顯示詳細資訊

-p:[磁盤] 顯示磁盤和分區的情況

iostat 結果清單字段釋義

[root@iz2ze2w3v37sit3vf71kuez ~]# iostat
Linux 3.10.0-514.26.2.el7.x86_64 (iz2ze2w3v37sit3vf71kuez)  2021年08月15日   _x86_64_  (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.76    0.00    0.61    0.02    0.00   98.61

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
vda               0.40         0.84         4.40    3985637   20823164      

cpu屬性值說明:

%user:
    CPU處在使用者模式下的時間百分比。
%nice:
    CPU處在帶NICE值的使用者模式下的時間百分比。
%system:
    CPU處在系統模式下的時間百分比。
%iowait:
    CPU等待輸入輸出完成時間的百分比。
%steal:
    管理程式維護另一個虛拟處理器時,虛拟CPU的無意識等待時間百分比。
%idle:
    CPU空閑時間百分比。      

備注:

如果%iowait的值過高,表示硬碟存在I/O瓶頸。

%idle值高,表示CPU較空閑,如果%idle值高但系統響應慢時,有可能是CPU等待配置設定記憶體,此時應加大記憶體容量。

%idle值如果持續低于10,那麼系統的CPU處理能力相對較低,表明系統中最需要解決的資源是CPU。

disk屬性值說明:

device:磁盤名稱
tps:每秒鐘發送到的I/O請求數.
Blk_read/s:每秒讀取的block數.
Blk_wrtn/s:每秒寫入的block數.
Blk_read:讀入的block總數.
Blk_wrtn:寫入的block總數.      

iostat -x 檢視cpu和磁盤的詳細資訊

[root@iz2ze2w3v37sit3vf71kuez ~]# iostat -x
Linux 3.10.0-514.26.2.el7.x86_64 (iz2ze2w3v37sit3vf71kuez)  2021年08月15日   _x86_64_  (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.76    0.00    0.61    0.02    0.00   98.61

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.27    0.04    0.36     0.84     4.40    26.06     0.00    5.64    8.75    5.28   0.58   0.02      

結果清單字段釋義

avgqu-sz:
    平均i/o隊列長度,建議不超過1
svctm:
    磁盤本身(磁盤讀寫)的耗時<4ms。平均每次裝置的IO操作的服務時間(毫秒),即delta(use)/delta(rio+wio)
await:
    作業系統每次IO的平均耗時,等待磁盤讀寫時間+svctm之和,機關是毫秒。
    一般情況下await大于svctm,他們的內插補點越小,則說明隊列越短。反之,內插補點越大,隊列越長,說明系統出了問題。
%util:
    磁盤繁忙程度。i/O請求占cpu的百分比,比率越大,說明越飽和。當%util達到1時,說明裝置帶寬已經被占滿。    
 rrqm/s:
 每秒進行merge的讀操作次數。即 rmerge/s
wrqm/s:
    每秒進行merge的寫操作次數。即 wmerge/s
r/s:
    每秒完成的讀 I/O 裝置次數。即 rio/s
w/s:
    每秒完成的寫 I/O 裝置次數。即 wio/s
rkB/s:
    每秒讀K位元組數。是 rsect/s 的一半,因為每扇區大小為512位元組。
wkB/s:
    每秒寫K位元組數。是 wsect/s 的一半。
avgrq-sz: 
    平均每次裝置I/O操作的資料大小 (扇區)。      

通過rkB/s與wkB/s可以判斷出,如果io很高的話,到底是讀導緻的還是寫導緻的。如果是讀導緻的,應該是記憶體不足。如果寫占比大,說明某個應用程式在寫。此時可以檢視哪個程式在寫東西,(寫檔案或者寫日志)

磁盤分以下三類:

機械硬碟(HDD)是傳統硬碟,單道尋址,比較慢。

固态磁盤,多通道尋址,比機械磁盤快。

混合硬碟(SSHD) 

12.2 iostat -d 檢視磁盤情況

[root@iz2ze2w3v37sit3vf71kuez ~]# iostat -d
Linux 3.10.0-514.26.2.el7.x86_64 (iz2ze2w3v37sit3vf71kuez)  2021年08月16日   _x86_64_  (1 CPU)

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
vda               0.42         0.91         4.73    4392681   22860432      

結果清單顯示

Device:
    磁盤名稱
tps:
    該裝置每秒的傳輸次數(Indicate the number of transfers per second that were issued to the device.)。
    "一次傳輸"意思是"一次I/O請求"。多個邏輯請求可能會被合并為"一次I/O請求"。"一次傳輸"請求的大小是未知的。
kB_read/s:
    每秒從裝置(drive expressed)讀取的資料量    
kB_wrtn/s:
    每秒向裝置(drive expressed)寫入的資料量;
kB_read: 
    讀取的總資料量;   
kB_wrtn:
    寫入的總數量資料量;這些機關都為Kilobytes。      

十三、sysbench介紹

1)sysbench安1.0裝

具體的安裝方式,按照這個連接配接:

---------------------

下面的安裝方式,也許會報錯

需要的軟體包:

automake

libtool

sysbench-1.0.zip

安裝:

sysbench-1.0:

wget https://github.com/akopytov/sysbench/archive/1.0.zip -O "sysbench-1.0.zip"       

下載下傳之後的名字是1.0.zip。

解壓之後為sysbench-1.0

cd sysbench-1.0      

執行autogen.sh用它來生成configure這個檔案

./autogen.sh      

執行

./configure && make && make install      

來完成sysbench的安裝

automake libtool:

yum install automake libtool      

2)sysbench介紹:

SysBench是一個子產品化的、跨平台、多線程基準測試工具,主要用于評估測試各種不同系統參數下的資料庫負載情況。它主要包括以下幾種方式的測試:

  • cpu性能
  • 磁盤io性能
  • 記憶體配置設定及傳輸速度
  • POSIX線程性能
  • 排程程式性能
  • 資料庫性能(OLTP基準測試)

3)通用選項說明

sysbench --help
Usage:
  sysbench [options]... [testname] [command]

Commands implemented by most tests: prepare run cleanup help

General options:
  --threads=N                     number of threads to use [1],建立測試線程的數目。預設為1.
  --events=N                      limit for total number of events [0],請求的最大數目,0代表不限制。
  --time=N                        limit for total execution time in seconds [10],最大執行時間,機關是s。預設是10s
  --forced-shutdown=STRING        number of seconds to wait after the --time limit before forcing shutdown, or 'off' to disable [off],超過max-time強制中斷。預設是off。
  --thread-stack-size=SIZE        size of stack per thread [64K],每個線程的堆棧大小。預設是64K。
  --rate=N                        average transactions rate. 0 for unlimited rate [0]
  --report-interval=N             periodically report intermediate statistics with a specified interval in seconds. 0 disables intermediate reports [0],指定每多少秒在螢幕上輸出一次結果
  --report-checkpoints=[LIST,...] dump full statistics and reset all counters at specified points in time. The argument is a list of comma-separated values representing the amount of time in seconds elapsed from start of test when report checkpoint(s) must be performed. Report checkpoints are off by default. []
  --debug[=on|off]                print more debugging info [off],是否顯示更多的調試資訊。預設是off。
  --validate[=on|off]             perform validation checks where possible [off],#在可能情況下執行驗證檢查。預設是off。
  --help[=on|off]                 print help and exit [off],#幫助資訊
  --version[=on|off]              print version and exit [off],#版本資訊
  --config-file=FILENAME          File containing command line options
  --tx-rate=N                     deprecated alias for --rate [0]
  --max-requests=N                deprecated alias for --events [0]
  --max-time=N                    deprecated alias for --time [0]
  --num-threads=N                 deprecated alias for --threads [1]

Pseudo-Random Numbers Generator options:
  --rand-type=STRING random numbers distribution {uniform,gaussian,special,pareto} [special]
  --rand-spec-iter=N number of iterations used for numbers generation [12]
  --rand-spec-pct=N  percentage of values to be treated as 'special' (for special distribution) [1]
  --rand-spec-res=N  percentage of 'special' values to use (for special distribution) [75]
  --rand-seed=N      seed for random number generator. When 0, the current time is used as a RNG seed. [0]
  --rand-pareto-h=N  parameter h for pareto distribution [0.2]

Log options:
  --verbosity=N verbosity level {5 - debug, 0 - only critical messages} [3],日志級别,預設為3,5=debug,0=隻包含重要資訊

  --percentile=N       percentile to calculate in latency statistics (1-100). Use the special value of 0 to disable percentile calculations [95]
  --histogram[=on|off] print latency histogram in report [off]

General database options:

  --db-driver=STRING  specifies database driver to use ('help' to get list of available drivers) [mysql]
  --db-ps-mode=STRING prepared statements usage mode {auto, disable} [auto]
  --db-debug[=on|off] print database-specific debug information [off]


Compiled-in database drivers:
  mysql - MySQL driver
  pgsql - PostgreSQL driver

mysql options:
  --mysql-host=[LIST,...]          MySQL server host [localhost]
  --mysql-port=[LIST,...]          MySQL server port [3306]
  --mysql-socket=[LIST,...]        MySQL socket
  --mysql-user=STRING              MySQL user [sbtest]
  --mysql-password=STRING          MySQL password []
  --mysql-db=STRING                MySQL database name [sbtest]
  --mysql-ssl[=on|off]             use SSL connections, if available in the client library [off]
  --mysql-ssl-cipher=STRING        use specific cipher for SSL connections []
  --mysql-compression[=on|off]     use compression, if available in the client library [off]
  --mysql-debug[=on|off]           trace all client library calls [off]
  --mysql-ignore-errors=[LIST,...] list of errors to ignore, or "all" [1213,1020,1205]
  --mysql-dry-run[=on|off]         Dry run, pretend that all MySQL client API calls are successful without executing them [off]

pgsql options:
  --pgsql-host=STRING     PostgreSQL server host [localhost]
  --pgsql-port=N          PostgreSQL server port [5432]
  --pgsql-user=STRING     PostgreSQL user [sbtest]
  --pgsql-password=STRING PostgreSQL password []
  --pgsql-db=STRING       PostgreSQL database name [sbtest]

Compiled-in tests:#測試項目
  fileio - File I/O test
  cpu - CPU performance test
  memory - Memory functions speed test,#記憶體
  threads - Threads subsystem performance test,#線程
  mutex - Mutex performance test#互斥性能測試

See 'sysbench <testname> help' for a list of options for each test.      

4)檢視幫助文檔&更多選項

-- 檢視總體幫助文檔

#sysbench  --help      

-- 查測試cpu的幫助文檔

#sysbench --test=cpu help
--cpu-max-prime=N  最大質數發生器數量。預設是10000      

-- 檢視IO測試的幫助文檔

#sysbench --test=fileio help

[root@iz2ze2w3v37sit3vf71kuez ~]# sysbench --test=fileio help
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
sysbench 1.0.17 (using system LuaJIT 2.0.4)

fileio options:
  --file-num=N                  number of files to create [128],建立測試檔案的數量。預設是128
  --file-block-size=N           block size to use in all IO operations [16384],測試時檔案塊的大小。預設是16384(16K)
  --file-total-size=SIZE        total size of files to create [2G],測試檔案的總大小。預設是2G
  --file-test-mode=STRING       檔案測試模式{seqwr(順序寫), seqrewr(順序讀寫), seqrd(順序讀), rndrd(随機讀), rndwr(随機寫), rndrw(随機讀寫)}                       
  --file-io-mode=STRING         檔案操作模式{sync(同步),async(異步),fastmmap(快速map映射),slowmmap(慢map映射)}。預設是sync
  --file-async-backlog=N        number of asynchronous operatons to queue per thread [128]
  --file-extra-flags=[LIST,...] 使用額外的标志來打開檔案{sync,dsync,direct} 。預設為空
  --file-fsync-freq=N           執行fsync()的頻率。(0 – 不使用fsync())。預設是100
  --file-fsync-all[=on|off]     每執行完一次寫操作就執行一次fsync。預設是off
  --file-fsync-end[=on|off]     在測試結束時才執行fsync。預設是on
  --file-fsync-mode=STRING      使用哪種方法進行同步{fsync, fdatasync}。預設是fsync
  --file-merged-requests=N      如果可以,合并最多的IO請求數(0 – 表示不合并)。預設是0
  --file-rw-ratio=N             測試時的讀寫比例,預設時為1.5,即可3:2。      

-- 檢視測試記憶體的幫助文檔

#sysbench --test=memory help

[root@iz2ze2w3v37sit3vf71kuez ~]# sysbench --test=memory help
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
sysbench 1.0.17 (using system LuaJIT 2.0.4)

memory options:
  --memory-block-size=SIZE  測試時記憶體塊大小。預設是1K
  --memory-total-size=SIZE    傳輸資料的總大小。預設是100G
  --memory-scope=STRING    記憶體通路範圍{global,local}。預設是global
  --memory-hugetlb=[on|off]  從HugeTLB池記憶體配置設定。預設是off
  --memory-oper=STRING     記憶體操作類型。{read, write, none} 預設是write
  --memory-access-mode=STRING存儲器存取方式{seq,rnd} 預設是seq      

-- 檢視測試線程的幫助文檔

#sysbench threads help

[root@iz2ze2w3v37sit3vf71kuez ~]# sysbench threads help
sysbench 1.0.17 (using system LuaJIT 2.0.4)

threads options:
  --thread-yields=N number of yields to do per request [1000],每個請求産生多少個線程。預設是1000
  --thread-locks=N  number of locks per thread [8],每個線程的鎖的數量。預設是8      

-- 檢視mutex的幫助文檔

#sysbench mutex help

[root@iz2ze2w3v37sit3vf71kuez ~]# sysbench mutex help
sysbench 1.0.17 (using system LuaJIT 2.0.4)

mutex options:
  --mutex-num=N   total size of mutex array [4096],數組互斥的總大小。預設是4096
  --mutex-locks=N number of mutex locks to do per thread [50000],每個線程互斥鎖的數量。預設是50000
  --mutex-loops=N number of empty loops to do outside mutex lock [10000],内部互斥鎖的空循環數量。預設是10000      

cpu性能測試

常用參數

  • –cpu-max-prime: 素數生成數量的上限
  • –threads: 線程數
  • –time: 運作時長,機關秒
  • –events: event上限次數

結果分析

[root@iz2ze2w3v37sit3vf71kuez ~]# sysbench cpu --cpu-max-prime=20000 --threads=2 run
sysbench 1.0.17 (using system LuaJIT 2.0.4)

Running the test with following options:
Number of threads: 2//線程數為2
Initializing random number generator from current time


Prime numbers limit: 20000//2萬個素數

Initializing worker threads...

Threads started!

CPU speed:
    events per second:   303.63

General statistics:
    total time:                          10.0040s //花費10s
    total number of events:              3038 //10秒内所有線程一共完成了3038次event

Latency (ms):
         min:                                    2.78 //最小耗時2.78ms
         avg:                                    6.57 //平均耗時6.57ms
         max:                                   43.05 //最大耗時43.05ms
         95th percentile:                       26.20 //95%在26.20ms完成
         sum:                                19968.27

Threads fairness:
    events (avg/stddev):           1519.0000/2.00
    execution time (avg/stddev):   9.9841/0.00      

磁盤IO性能測試

#準備資料
sysbench --test=fileio --file-total-size=2G prepare
#運作測試
[root@zijie ~]# sysbench --test=fileio --file-total-size=2G --file-test-mode=rndrw  --max-time=30 --max-requests=0 run
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
WARNING: --max-time is deprecated, use --time instead
sysbench 1.0.18 (using bundled LuaJIT 2.1.0-beta2)

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time


Extra file open flags: (none)
128 files, 16MiB each
2GiB total file size
Block size 16KiB
Number of IO requests: 0
Read/Write ratio for combined random IO test: 1.50
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing random r/w test
Initializing worker threads...

Threads started!


File operations:
    reads/s:                      612.68 
    writes/s:                     408.44 
    fsyncs/s:                     1307.77

Throughput:
    read, MiB/s:                  9.57 //讀吞吐
    written, MiB/s:               6.38 //寫吞吐

General statistics:
    total time:                          30.0436s
    total number of events:              69851

Latency (ms):
         min:                                    0.00
         avg:                                    0.43
         max:                                  213.95
         95th percentile:                        1.76
         sum:                                29921.46

Threads fairness:
    events (avg/stddev):           69851.0000/0.00
    execution time (avg/stddev):   29.9215/0.00
#清理資料
sysbench --test=fileio --file-total-size=2G cleanup      

記憶體配置設定及傳輸速度測試

參數詳解:

–memory-block-size=SIZE 測試記憶體塊的大小,預設為1K

–memory-total-size=SIZE 資料傳輸的總大小,預設為100G

–memory-scope=STRING 記憶體通路的範圍,包括全局和本地範圍,預設為global

–memory-hugetlb=[on|off] 是否從HugeTLB池配置設定記憶體的開關,預設為off

–memory-oper=STRING 記憶體操作的類型,包括read, write, none,預設為write

–memory-access-mode=STRING 記憶體通路模式,包括seq,rnd兩種模式,預設為seq

結果分析

#順序配置設定
[root@zijie ~]# sysbench --num-threads=12 --max-requests=10000 --test=memory --memory-block-size=8K --memory-total-size=1G --memory-access-mode=seq run
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
WARNING: --num-threads is deprecated, use --threads instead
WARNING: --max-requests is deprecated, use --events instead
sysbench 1.0.18 (using bundled LuaJIT 2.1.0-beta2)

Running the test with following options:
Number of threads: 12
Initializing random number generator from current time


Running memory speed test with the following options:
  block size: 8KiB
  total size: 1024MiB
  operation: write
  scope: global

Initializing worker threads...

Threads started!

Total operations: 131064 (1068428.85 per second)

1023.94 MiB transferred (8347.10 MiB/sec)


General statistics:
    total time:                          0.1206s
    total number of events:              131064

Latency (ms):
         min:                                    0.00
         avg:                                    0.00
         max:                                    0.69
         95th percentile:                        0.00
         sum:                                   97.04

Threads fairness:
    events (avg/stddev):           10922.0000/0.00
    execution time (avg/stddev):   0.0081/0.00

#随機配置設定
[root@zijie ~]# sysbench --num-threads=12 --max-requests=10000 --test=memory --memory-block-size=8K --memory-total-size=1G --memory-access-mode=rnd run
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
WARNING: --num-threads is deprecated, use --threads instead
WARNING: --max-requests is deprecated, use --events instead
sysbench 1.0.18 (using bundled LuaJIT 2.1.0-beta2)

Running the test with following options:
Number of threads: 12
Initializing random number generator from current time


Running memory speed test with the following options:
  block size: 8KiB
  total size: 1024MiB
  operation: write
  scope: global

Initializing worker threads...

Threads started!

Total operations: 131064 (246216.85 per second)

1023.94 MiB transferred (1923.57 MiB/sec)


General statistics:
    total time:                          0.5304s
    total number of events:              131064

Latency (ms):
         min:                                    0.00
         avg:                                    0.04
         max:                                  355.12
         95th percentile:                        0.00
         sum:                                 4756.95

Threads fairness:
    events (avg/stddev):           10922.0000/0.00
    execution time (avg/stddev):   0.3964/0.09      

POSIX線程性能測試

常用參數

  • –thread-yields=N 每個請求産生多少個線程。預設是1000
  • –thread-locks=N 每個線程的鎖的數量。預設是8
[root@zijie ~]# sysbench --test=threads --num-threads=64 --thread-yields=100 --thread-locks=2 run
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
WARNING: --num-threads is deprecated, use --threads instead
sysbench 1.0.18 (using bundled LuaJIT 2.1.0-beta2)

Running the test with following options:
Number of threads: 64
Initializing random number generator from current time


Initializing worker threads...

Threads started!


General statistics:
    total time:                          10.0213s
    total number of events:              35298

Latency (ms):
         min:                                    0.26
         avg:                                   18.15
         max:                                 6190.05
         95th percentile:                        4.33
         sum:                               640679.20

Threads fairness:
    events (avg/stddev):           551.5312/2416.65
    execution time (avg/stddev):   10.0106/0.01      

排程程式性能

常用參數

  • –mutex-num=N 數組互斥的總大小。預設是4096
  • –mutex-locks=N 每個線程互斥鎖的數量。預設是50000
  • –mutex-loops=N 内部互斥鎖的空循環數量。預設是10000

結果分析

[root@zijie ~]# sysbench  --num-threads=2  --test=mutex --mutex-num=1024 --mutex-locks=10000 --mutex-loops=10000 run
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
WARNING: --num-threads is deprecated, use --threads instead
sysbench 1.0.18 (using bundled LuaJIT 2.1.0-beta2)

Running the test with following options:
Number of threads: 2
Initializing random number generator from current time


Initializing worker threads...

Threads started!


General statistics:
    total time:                          0.0729s
    total number of events:              2

Latency (ms):
         min:                                   57.09
         avg:                                   60.43
         max:                                   63.77
         95th percentile:                       63.32
         sum:                                  120.86

Threads fairness:
    events (avg/stddev):           1.0000/0.00
    execution time (avg/stddev):   0.0604/0.00      

十四、stress工具介紹

Linux壓力測試工具Stress

安裝

yum install stress      

十五、mapstat指令介紹

十六、案例分析-上下文切換

示範伺服器 centos 7

ssh [email protected]

1)檢視正常情況下的上下文切換情況

vmstat 5

每5秒更新一下資料

一文搞清楚Linux性能監控及定位

2)模拟多線程切換

建立20個線程,持續300秒

#sysbench threads --threads=20 --time=300 run

紅色框起來的部分,那時我們開始加壓。in 和 cs 明顯升高

vmstat 5      
一文搞清楚Linux性能監控及定位
[root@iz2ze2w3v37sit3vf71kuez ~]# sysbench threads --threads=20  --time=300 run
sysbench 1.0.17 (using system LuaJIT 2.0.4)

Running the test with following options:
Number of threads: 20
Initializing random number generator from current time


Initializing worker threads...

Threads started!


General statistics:
    total time:                          300.0129s
    total number of events:              274087

Latency (ms):
         min:                                    0.85
         avg:                                   21.89
         max:                                  391.57
         95th percentile:                       61.08
         sum:                              5999952.14

Threads fairness:
    events (avg/stddev):           13704.3500/90.91
    execution time (avg/stddev):   299.9976/0.00      

 使用pidstat檢視線程的上下文切換情況

[root@iz2ze2w3v37sit3vf71kuez ~]# pidstat 5
Linux 3.10.0-514.26.2.el7.x86_64 (iz2ze2w3v37sit3vf71kuez)  2021年08月16日   _x86_64_  (1 CPU)

18時00分42秒   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
18時00分47秒     0     20566    7.58   91.62    0.00    0.00   99.20     0  sysbench
18時00分47秒     0     31845    0.00    0.20    0.00    0.00    0.20     0  aliyun-service      
一文搞清楚Linux性能監控及定位

pidstat -w

檢視程序的上下文切換情況

一文搞清楚Linux性能監控及定位

分析:

1,vmstat指令下,發現cs列的上下文切換從1227已經漲到了140多萬

R列:就緒隊列長度已經到了9,遠遠超過了cpu的個數1,是以會産生大量的cpu競争

us和sy列:cpu使用率加起來已經到100%其中系統 CPU 使用率,也就是 sy 列高達 91%,說明 CPU 主要是被核心占用了

in 列:中斷次數也上升到了 1412左右,說明中斷處理也是個潛在的問題

綜合這幾個名額,可以知道,系統的就緒隊列過長,也就是正在運作和等待 CPU 的程序數過多,導緻了大量的上下文切換,而上下文切換又導緻了系統 CPU 的占用率升高

2,從 pidstat 的輸出你可以發現,CPU 使用率的升高果然是 sysbench 導緻的,它的 CPU使用率已經達到了 99%。但上下文切換則是來自其他程序,包括主動上下文切換最高的rcu_sched

3,**使用-wt 參數表示輸出線程的上下文切換名額 **

雖然 sysbench 程序(也就是主線程)的上下文切換次數看起來并不多,但它的子線程的上下文切換次數卻有很多。看來,上下文切換罪魁禍首,還是過多的sysbench 線程。

pidstat -wt

一文搞清楚Linux性能監控及定位

重點:

在日常工作中,使用pidstat 檢視上下文切換的時候,建議使用pidstat -w 和pidstat -wt各檢視一下。

因為如果使用-w,隻是檢視程序的資料,當線程造成大量上下文切換時,是不會顯示線程的資料。是以需要單獨看一下線程的資料

Linux strace指令詳解

簡介

strace常用來跟蹤程序執行時的系統調用和所接收的信号。

在Linux世界,程序不能直接通路硬體裝置,當程序需要通路硬體裝置(比如讀取磁盤檔案,接收網絡資料等等)時,必須由使用者态模式切換至核心态模式,通 過系統調用通路硬體裝置。

strace可以跟蹤到一個程序産生的系統調用,包括參數,傳回值,執行消耗的時間。

輸出參數含義

strace cat /dev/null

[root@iz2ze2w3v37sit3vf71kuez opt]# strace cat /dev/null
execve("/usr/bin/cat", ["cat", "/dev/null"], [/* 35 vars */]) = 0
brk(0)                                  = 0x1ea6000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f10ecdbe000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=29072, ...}) = 0
mmap(NULL, 29072, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f10ecdb6000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2118128, ...}) = 0
mmap(NULL, 3932672, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f10ec7de000
mprotect(0x7f10ec995000, 2093056, PROT_NONE) = 0
mmap(0x7f10ecb94000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x7f10ecb94000
mmap(0x7f10ecb9a000, 16896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f10ecb9a000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f10ecdb5000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f10ecdb3000
arch_prctl(ARCH_SET_FS, 0x7f10ecdb3740) = 0
mprotect(0x7f10ecb94000, 16384, PROT_READ) = 0
mprotect(0x60b000, 4096, PROT_READ)     = 0
mprotect(0x7f10ecdbf000, 4096, PROT_READ) = 0
munmap(0x7f10ecdb6000, 29072)           = 0
brk(0)                                  = 0x1ea6000
brk(0x1ec7000)                          = 0x1ec7000
brk(0)                                  = 0x1ec7000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f10e62b5000
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
open("/dev/null", O_RDONLY)             = 3
fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "", 65536)                      = 0
close(3)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++      

每一行都是一條系統調用,等号左邊是系統調用的函數名及其參數,右邊是該調用的傳回值。

strace 顯示這些調用的參數并傳回符号形式的值。strace 從核心接收資訊,而且不需要以任何特殊的方式來建構核心。

strace參數

-c 統計每一系統調用的所執行的時間,次數和出錯的次數等.
-d 輸出strace關于标準錯誤的調試資訊.
-f 跟蹤由fork調用所産生的子程序.
-ff 如果提供-o filename,則所有程序的跟蹤結果輸出到相應的filename.pid中,pid是各程序的程序号.
-F 嘗試跟蹤vfork調用.在-f時,vfork不被跟蹤.
-h 輸出簡要的幫助資訊.
-i 輸出系統調用的入口指針.
-q 禁止輸出關于脫離的消息.
-r 列印出相對時間關于,,每一個系統調用.
-t 在輸出中的每一行前加上時間資訊.
-tt 在輸出中的每一行前加上時間資訊,微秒級.
-ttt 微秒級輸出,以秒了表示時間.
-T 顯示每一調用所耗的時間.
-v 輸出所有的系統調用.一些調用關于環境變量,狀态,輸入輸出等調用由于使用頻繁,預設不輸出.
-V 輸出strace的版本資訊.
-x 以十六進制形式輸出非标準字元串
-xx 所有字元串以十六進制形式輸出.
-a column
設定傳回值的輸出位置.預設 為40.
-e expr
指定一個表達式,用來控制如何跟蹤.格式如下:
[qualifier=][!]value1[,value2]...
qualifier隻能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用來限定的符号或數字.預設的 qualifier是 trace.感歎号是否定符号.例如:
-eopen等價于 -e trace=open,表示隻跟蹤open調用.而-etrace!=open表示跟蹤除了open以外的其他調用.有兩個特殊的符号 all 和 none.
注意有些shell使用!來執行曆史記錄裡的指令,是以要使用\\.
-e trace=set
隻跟蹤指定的系統 調用.例如:-e trace=open,close,rean,write表示隻跟蹤這四個系統調用.預設的為set=all.
-e trace=file
隻跟蹤有關檔案操作的系統調用.
-e trace=process
隻跟蹤有關程序控制的系統調用.
-e trace=network
跟蹤與網絡有關的所有系統調用.
-e strace=signal
跟蹤所有與系統信号有關的 系統調用
-e trace=ipc
跟蹤所有與程序通訊有關的系統調用
-e abbrev=set
設定 strace輸出的系統調用的結果集.-v 等與 abbrev=none.預設為abbrev=all.
-e raw=set
将指 定的系統調用的參數以十六進制顯示.
-e signal=set
指定跟蹤的系統信号.預設為all.如 signal=!SIGIO(或者signal=!io),表示不跟蹤SIGIO信号.
-e read=set
輸出從指定檔案中讀出 的資料.例如:
-e read=3,5
-e write=set
輸出寫入到指定檔案中的資料.
-o filename
将strace的輸出寫入檔案filename
-p pid
跟蹤指定的程序pid.
-s strsize
指定輸出的字元串的最大長度.預設為32.檔案名一直全部輸出.
-u username
以username 的UID和GID執行被跟蹤的指令      

指令執行個體

通用的完整用法:

strace -o output.txt -T -tt -e trace=all -p 28979

上面的含義是 跟蹤28979程序的所有系統調用(-e trace=all),并統計系統調用的花費時間,以及開始時間(并以可視化的時分秒格式顯示),最後将記錄結果存在output.txt檔案裡面。

strace案例

用strace調試程式

在理想世界裡,每當一個程式不能正常執行一個功能時,它就會給出一個有用的錯誤提示,告訴你在足夠的改正錯誤的線索。但遺憾的是,我們不是生活在理想世界 裡,有時候一個程式出現了問題,你無法找到原因。

這就是調試程式出現的原因。

strace是一個必不可少的 調試工具,strace用來監視系統調用。

你不僅可以調試一個新開始的程式,也可以調試一個已經在運作的程式(把strace綁定到一個已有的PID上 面)。

這裡具體的案例分析,可以檢視原部落格的案例分析:​​Linux strace指令詳解_Linux教程_Linux公社-Linux系統門戶網站​​

也可以看以下案例分析-場景六。

lsof

參考連結:

​​https://www.jianshu.com/p/a3aa6b01b2e1​​

lsof(list open files)是一個檢視程序打開的檔案的工具。

在 linux 系統中,一切皆檔案。通過檔案不僅僅可以通路正常資料,還可以通路網絡連接配接和硬體。是以 lsof 指令不僅可以檢視程序打開的檔案、目錄,還可以檢視程序監聽的端口等 socket 相關的資訊。本文将介紹 lsof 指令的基本用法,本文中 demo 的示範環境為 centos 7。

常用選項

-a 訓示其它選項之間為與的關系
-c <程序名> 輸出指定程序所打開的檔案
-d <檔案描述符> 列出占用該檔案号的程序
+d <目錄> 輸出目錄及目錄下被打開的檔案和目錄(不遞歸)
+D <目錄> 遞歸輸出及目錄下被打開的檔案和目錄
-i <條件> 輸出符合條件與網絡相關的檔案
-n 不解析主機名
-p <程序号> 輸出指定 PID 的程序所打開的檔案
-P 不解析端口号
-t 隻輸出 PID
-u 輸出指定使用者打開的檔案
-U 輸出打開的 UNIX domain socket 檔案
-h 顯示幫助資訊
-v 顯示版本資訊      

檢視使用者資訊

可以擷取各種使用者的資訊,以及它們在系統上正幹着的事情,包括它們的網絡活動、對檔案的操作等。

使用-u顯示指定使用者打開了什麼

systemd-u   350 root  txt       REG              253,1    361376     661440 /usr/lib/systemd/systemd-udevd
systemd-u   350 root  mem       REG              253,1     62184     657587 /usr/lib64/libnss_files-2.17.so
systemd-u   350 root  mem       REG              253,1   7259752    1179976 /etc/udev/hwdb.bin
systemd-u   350 root  mem       REG              253,1     19888     657916 /usr/lib64/libattr.so.1.1.0
systemd-u   350 root  DEL       REG              253,1               657746 /usr/lib64/libz.so.1.2.7;60d1c6ab
systemd-u   350 root  mem       REG              253,1    157424     657758 /usr/lib64/liblzma.so.5.2.2
systemd-u   350 root  mem       REG              253,1     20040     657784 /usr/lib64/libuuid.so.1.3.0      

指令和程序

可以檢視指定程式或程序由什麼啟動,這通常會很有用,而你可以使用lsof通過名稱或程序ID過濾來完成這個任務。下面列出了一些選項:

使用-c檢視指定的指令正在使用的檔案和網絡連接配接

1.  #  lsof  -c syslog-ng

3.  COMMAND    PID USER   FD   TYPE     DEVICE    SIZE       NODE NAME
4.  syslog-ng 7547 root  cwd    DIR 3,3  4096  2  /
5.  syslog-ng 7547 root  rtd    DIR 3,3  4096  2  /
6.  syslog-ng 7547 root  txt    REG 3,3  113524  1064970  /usr/sbin/syslog-ng
7.  -- snipped --
      

使用-p檢視指定程序ID已打開的内容

1.  #  lsof  -p 10075

3.  -- snipped --
4.  sshd  10068 root  mem    REG 3,3  34808  850407  /lib/libnss_files-2.4.so
5.  sshd  10068 root  mem    REG 3,3  34924  850409  /lib/libnss_nis-2.4.so
6.  sshd  10068 root  mem    REG 3,3  26596  850405  /lib/libnss_compat-2.4.so
7.  sshd  10068 root  mem    REG 3,3  200152  509940  /usr/lib/libssl.so.0.9.7
8.  sshd  10068 root  mem    REG 3,3  46216  510014  /usr/lib/liblber-2.3
9.  sshd  10068 root  mem    REG 3,3  59868  850413  /lib/libresolv-2.4.so
10.  sshd  10068 root  mem    REG 3,3  1197180  850396  /lib/libc-2.4.so
11.  sshd  10068 root  mem    REG 3,3  22168  850398  /lib/libcrypt-2.4.so
12.  sshd  10068 root  mem    REG 3,3  72784  850404  /lib/libnsl-2.4.so
13.  sshd  10068 root  mem    REG 3,3  70632  850417  /lib/libz.so.1.2.3
14.  sshd  10068 root  mem    REG 3,3  9992  850416  /lib/libutil-2.4.so
15.  -- snipped --      

案例分析-平均負載

準備

預先安裝 stress 和 sysstat 包

工具:iostat、mpstat、pidstat

stress 是一個 Linux 系統壓力測試工具,

sysstat 包含了常用的 Linux 性能工具,用來監控和分析系統的性能。這個包的兩個指令 mpstat 和 pidstat。

mpstat 是一個常用的多核 CPU 性能分析工具,用來實時檢視每個 CPU 的性能名額,以及所有 CPU 的平均名額。

pidstat 是一個常用的程序性能分析工具,用來實時檢視程序的 CPU、記憶體、I/O 以及上下文切換等性能名額

場景一:CPU密集型程序

第一個終端運作 stress 指令,模拟一個 CPU 使用率 100% 的場景

如果linux伺服器,隻有一核cpu,執行:

stress --cpu 1 --timeout 600      
[root@iz2ze2w3v37sit3vf71kuez ~]# stress --cpu 1 --timeout 600
stress: info: [20859] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd      

如果linux伺服器,兩核cpu,執行:

stress --cpu 2 --timeout 600      

在第二個終端運作 top 檢視平均負載的變化情況

一文搞清楚Linux性能監控及定位

 負載達到了2.5,cpu使用率達到了100%

在第三個終端運作 mpstat 檢視 CPU 使用率的變化情況:

mpstat -P ALL 5      

-P ALL 表示監控所有cpu

5 表示間隔5秒輸出一次資料

一文搞清楚Linux性能監控及定位

我的機器隻有一個CPU。下圖是一個多cpu截圖(來源與網絡)

一文搞清楚Linux性能監控及定位

場景二:

stress -i 1 --timeout 600      
一文搞清楚Linux性能監控及定位

負載上升,sy 消耗很大。si中斷是0,wa值比較大,則是很有可能是io導緻的。

場景三

stress -c 8 --timeout 600