linux性能定位思路:

簡介:
本文主要從以下四個次元名額,來講解Linux監控及性能問題定位
CPU 、Memory 、 IO 、Network
一、top指令解析
使用top指令檢視程序使用資源情況
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
顯示完整指令
top -c
或者先輸入top指令,然後再按c,來切換顯示程序的完成指令
注意:
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,意味着大橋上一輛車也沒有。
系統負荷為0.5,意味着大橋一半的路段有車。
系統負荷為1.0,意味着大橋的所有路段都有車,也就是說大橋已經"滿"了。但是必須注意的是,直到此時大橋還是能順暢通行的。
系統負荷為1.7,意味着車輛太多了,大橋已經被占滿了(100%),後面等着上橋的車輛為橋面車輛的70%。以此類推,系統負荷2.0,意味着等待上橋的車輛與橋面的車輛一樣多;系統負荷3.0,意味着等待上橋的車輛是橋面車輛的2倍。總之,當系統負荷大于1,後面的車輛就必須等待了;系統負荷越大,過橋就必須等得越久。
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就意味着大橋有兩根車道了,通車能力翻倍了。
是以,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列,為每個程序的狀态。
線程的就緒狀态與運作狀态,都是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。
%Cpu(s),s說明是複數,存在多個cpu,我們按1,可以展開
cpu0負責所有cpu核心的排程。
使用top指令,檢視cpu資料時,發現cpu0的使用率遠遠高于cpu1,可能導緻問題的原因
1、cpu排程有問題
2、某些應用程式
5.2 雲伺服器的cpu
我檢視了一下自己買的華為雲服務的cpu規格
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百分比
兩列: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 記憶體
KiB Swap 記憶體:
交換區記憶體,一小部分在記憶體,大部分在磁盤上。在磁盤上開辟了一塊空間,當作記憶體來使用。最終運作在磁盤上。記憶體的運作速度至少是磁盤運作速度的幾百倍。是以交換區的記憶體,運作速度非常慢。swap used值變高,說明實體記憶體不夠用,而且系統開始變慢。從功能上講,交換分區主要是在記憶體不夠用的時候,将部分記憶體上的資料交換到swap空間上,以便讓系統不會因記憶體不夠用而導緻oom或者更緻命的情況出現。
分析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
cache 緩存:
緩存的是最近一段時間頻繁從磁盤裡取的檔案(熱點資料),緩存也是在記憶體裡。
這些熱點資料,用完之後并沒有丢棄,而是緩存在了記憶體裡,為了避免頻繁的從磁盤裡互動資料。
當記憶體緊張時,緩存資料會變小。
buffers緩沖:
向磁盤裡寫的資料。
使用top指令,檢視程序的列資訊。
隻需要關注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 上運作才能完成。
每次上下文切換都需要幾十納秒到數微秒的 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秒重新整理一次結果,隻要不停止,會持續顯示重新整理後的資料
vmstat 10 5
10秒重新整理一次結果,一共顯示5次資料
字段說明
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 這個工具,來查詢系統的上下文切換情況 ,主要關注以下幾項。
主要關注以下四個資料:
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次。
字段說明
- cswch ,表示每秒主動任務上下文切換(voluntary context switches)的次數
- nvcswch ,表示每秒被動任務上下文切換的(non voluntary context switches)次數
所謂主動上下文切換,是指程序無法擷取所需資源,導緻的上下文切換。比如說,
I/O、記憶體等系統資源不足時,就會發生主動上下文切換。
而被動上下文切換,則是指程序由于時間片已到等原因,被系統強制排程,進而發生
的上下文切換。比如說,大量程序都在争搶 CPU 時,就容易發生被動上下文切換。
pidstat -wt
檢視程序及線程的上下文切換情況
注意:
pidstat -w 5 2
與
pidstat -wt 5 2
-w是隻檢視程序上下文切換,-wt檢視程序及線程的上下文切換情況。
如上圖,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 [選項] [<時間間隔>] [<次數>]
指令參數:
-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
1)檢視正常情況下的上下文切換情況
vmstat 5
每5秒更新一下資料
2)模拟多線程切換
建立20個線程,持續300秒
#sysbench threads --threads=20 --time=300 run
紅色框起來的部分,那時我們開始加壓。in 和 cs 明顯升高
vmstat 5
[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
pidstat -w
檢視程序的上下文切換情況
分析:
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
重點:
在日常工作中,使用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 檢視平均負載的變化情況
負載達到了2.5,cpu使用率達到了100%
在第三個終端運作 mpstat 檢視 CPU 使用率的變化情況:
mpstat -P ALL 5
-P ALL 表示監控所有cpu
5 表示間隔5秒輸出一次資料
我的機器隻有一個CPU。下圖是一個多cpu截圖(來源與網絡)
場景二:
stress -i 1 --timeout 600
負載上升,sy 消耗很大。si中斷是0,wa值比較大,則是很有可能是io導緻的。
場景三
stress -c 8 --timeout 600