性能優化的兩個核心指標——"吞吐"和"延遲",這是從應用負載的視角來進行考察系統性能,直接影響了產品終端的用戶體驗。與之對應的是從系統資源的視角出發的指標,好比資源使用率、飽和度等。python
咱們知道,隨着應用負載的增長,系統資源的使用也會升高,甚至達到極限。而性能問題的本質,就是系統資源已經達到瓶頸,但請求的處理卻還不夠快,沒法支撐更多的請求。ios
性能分析,其實就是找出應用或系統的瓶頸,並設法去避免或者緩解他們,從而更高效地利用系統資源處理更多的請求。這包含了一系列的步驟,好比下面這六個步驟。redis
選擇指標評估應用程序和系統的性能數據庫
爲應用程序和系統設置性能目標緩存
進行性能基準測試性能優化
性能分析定位瓶頸bash
優化系統和應用程序服務器
性能監控和告警多線程
這個圖是Linux性能分析最重要的參考資料之一,它告訴你,在Linux不一樣子系統出現性能問題後,應該用什麼樣的工具來觀測和分析。app
好比,當遇到IO性能問題時,能夠參考圖片下方的IO子系統,使用iostat、iotop、blktrace等工具分析磁盤IO的瓶頸。
平均負載是指單位時間內,系統處於可運行狀態和不可中斷狀態的平均進程數,也就是平均活躍進程數,它和CPU使用率並無直接關係。
可運行狀態的進程,是指正在使用CPU或者正在等待CPU的進程,也就是ps命令查看進程狀態中的R狀態(Running或Runnable)。
不可中斷狀態的進程,是指正處於內核態關鍵流程中的進程,而且這些流程是不可打斷的,好比最長間的是等待硬件設備的IO響應,也就是ps命令查看進程狀態中的D狀態。例如,當一個進程向磁盤讀取數據時,爲了保證數據的一致性,在獲得磁盤迴復前,它是不能被其餘進程或者中斷打斷,這個時候的進程處於不可中斷狀態。若是此時的進程被打斷,就容易出現磁盤數據與進程數據不一致的問題。因此,不可中斷狀態其實是系統對進程和硬件設備的一種保護機制。所以平均負載能夠理解爲平均活躍進程數。平均進程活躍數,直觀上的理解就是單位時間內的活躍進程數,但其實是活躍進程數的指數衰減平均值,能夠直接理解爲活躍進程數的平均值。
若是當平均負載爲2時,就意味着
在只有2個CPU的系統上,意味着全部的CPU都恰好被徹底佔用。
在4個CPU的系統上,意味着CPU有50%的空閒。
在1個CPU的系統中,意味着有一半的進程競爭不到CPU
平均負載最理想的狀況是等於CPU個數,因此在評判平均負載時,首先要知道系統有幾個CPU,有了CPU個數,咱們能夠判斷出,當平均負載比CPU個數還大的時候,系統已經出現了過載。
三個不一樣時間間隔的平均負載,其實給咱們提供了,分析系統負載趨勢的數據來源,讓咱們更能全面、更立體地理解目前的負載狀況。
若是1分鐘、5分鐘、15分鐘的三個值基本相同,或者相差不大,那就說明系統負載很平穩。
但若是1分鐘的值遠小於15分鐘的值,就說明系統最近1分鐘的負載在減小,而過去15分鐘內卻有很大的負載
若是1分鐘的值遠大於15分鐘的值,就說明最近1分鐘的負載在增長,這種增長有可能只是臨時性的,也有可能還會持續增長下去,因此就須要持續觀察。一旦1分鐘的平均負載接近或者超過CPU的個數,就意味着系統正在發生過載的問題,這時就得分析調查是哪裏致使的問題,並要想辦法優化。
分析排查負載太高的問題須要把系統的平均負載監控起來,而後根據更多的歷史數據,判斷負載的變化趨勢,當發生負載有明顯升高趨勢時,好比說負載翻倍了,再去作分析和調查
CPU密集型進程,使用大量CPU會致使平均負載升高
IO密集型進程,等待IO也會致使平均負載升高,單CPU使用率不必定很高。
大量等待CPU的進程調度也會致使平均負載升高,此時的CPU使用率也會比較高。
mpstat是一個經常使用的多核CPU性能分析工具,用來實時查看每一個CPU的性能指標,以及全部CPU的平均指標
[root@localhost ~]# mpstat 2 Linux 2.6.32-431.el6.x86_64 (localhost.localdomain) 04/27/2020 _x86_64_ (4 CPU) 05:49:27 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle 05:49:29 PM all 0.50 0.00 0.50 0.00 0.00 0.00 0.00 0.00 99.00 05:49:31 PM all 0.38 0.00 0.38 0.00 0.00 0.00 0.00 0.00 99.25 05:49:33 PM all 0.25 0.00 0.50 0.00 0.00 0.00 0.00 0.00 99.25 05:49:35 PM all 0.25 0.00 0.50 0.00 0.00 0.00 0.00 0.00 99.25
pidstat是一個經常使用的進程性能分析工具,用來實時查看進程的CPU、內存、IO以及山下文切換等性能指標。
[root@localhost ~]# stress --cpu 1 --timeout 600 stress: info: [6168] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd [root@localhost ~]# uptime 17:59:36 up 405 days, 8:51, 2 users, load average: 0.99, 0.75, 0.35 [root@localhost ~]# mpstat -P ALL 2 3 Linux 2.6.32-431.el6.x86_64 (localhost.localdomain) 04/27/2020 _x86_64_ (4 CPU) 05:57:44 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle 05:57:46 PM all 25.41 0.00 0.50 0.00 0.00 0.00 0.00 0.00 74.09 05:57:46 PM 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 05:57:46 PM 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 05:57:46 PM 2 1.01 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.99 05:57:46 PM 3 0.00 0.00 2.01 0.00 0.00 0.00 0.00 0.00 97.99 05:57:46 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle 05:57:48 PM all 25.37 0.00 0.50 0.00 0.00 0.00 0.00 0.00 74.12 05:57:48 PM 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 05:57:48 PM 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 05:57:48 PM 2 1.00 0.00 0.50 0.00 0.00 0.00 0.00 0.00 98.50 05:57:48 PM 3 1.00 0.00 1.49 0.00 0.00 0.00 0.00 0.00 97.51 [root@localhost ~]# pidstat -u 5 1 Linux 2.6.32-431.el6.x86_64 (localhost.localdomain) 04/27/2020 _x86_64_ (4 CPU) 06:08:20 PM PID %usr %system %guest %CPU CPU Command 06:08:25 PM 3360 0.00 0.20 0.00 0.20 0 redis-server 06:08:25 PM 3593 0.20 0.20 0.00 0.40 3 bash 06:08:25 PM 3723 0.60 0.20 0.00 0.80 0 netdata 06:08:25 PM 3748 0.20 0.00 0.00 0.20 0 python 06:08:25 PM 7276 100.00 0.00 0.00 100.00 1 stress 06:08:25 PM 7289 0.00 0.20 0.00 0.20 3 pidstat 06:08:25 PM 25850 0.40 1.00 0.00 1.40 2 apps.plugin Average: PID %usr %system %guest %CPU CPU Command Average: 3360 0.00 0.20 0.00 0.20 - redis-server Average: 3593 0.20 0.20 0.00 0.40 - bash Average: 3723 0.60 0.20 0.00 0.80 - netdata Average: 3748 0.20 0.00 0.00 0.20 - python Average: 7276 100.00 0.00 0.00 100.00 - stress Average: 7289 0.00 0.20 0.00 0.20 - pidstat Average: 25850 0.40 1.00 0.00 1.40 - apps.plugin
首先利用stress模擬一個CPU使用率100%的狀況,而後利用uptime觀察平均負載的變化狀況,最後使用mpstat查看每一個CPU使用率的狀況;從uptime命令能夠看到1分鐘內的平均負載==1,而mpstat命令看到CPU1的使用率爲100%,且都是在用戶態空間使用的CPU,說明致使負載升高是因爲CPU使用率比較高引發的負載升高;最後使用pidstat監測,發現是stress進程CPU使用爲100%
IO密集型應用
[root@localhost ~]# stress -i 1 --timeout 600 stress: info: [7582] dispatching hogs: 0 cpu, 1 io, 0 vm, 0 hdd [root@localhost ~]# uptime 18:13:11 up 405 days, 9:05, 2 users, load average: 0.80, 0.66, 0.46 [root@localhost ~]# uptime 18:13:16 up 405 days, 9:05, 2 users, load average: 0.82, 0.66, 0.47 [root@localhost ~]# uptime 18:13:24 up 405 days, 9:05, 2 users, load average: 0.84, 0.67, 0.47 [root@localhost ~]# uptime 18:13:30 up 405 days, 9:05, 2 users, load average: 0.86, 0.68, 0.47 [root@localhost ~]# uptime 18:13:39 up 405 days, 9:05, 2 users, load average: 0.88, 0.69, 0.48 [root@localhost ~]# uptime 18:13:47 up 405 days, 9:05, 2 users, load average: 0.90, 0.70, 0.48 [root@localhost ~]# uptime 18:14:05 up 405 days, 9:06, 2 users, load average: 0.92, 0.71, 0.49 [root@localhost ~]# uptime 18:14:22 up 405 days, 9:06, 2 users, load average: 0.94, 0.73, 0.50 [root@localhost ~]# uptime 18:14:47 up 405 days, 9:06, 2 users, load average: 0.96, 0.74, 0.51 [root@localhost ~]# uptime 18:15:28 up 405 days, 9:07, 2 users, load average: 0.98, 0.78, 0.53 [root@localhost ~]# mpstat -P ALL 5 1 Linux 2.6.32-431.el6.x86_64 (localhost.localdomain) 04/27/2020 _x86_64_ (4 CPU) 06:17:07 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle 06:17:12 PM all 0.35 0.00 24.90 0.05 0.00 0.00 0.00 0.00 74.70 06:17:12 PM 0 0.00 0.00 0.40 0.00 0.00 0.00 0.00 0.00 99.60 06:17:12 PM 1 0.00 0.00 97.79 0.00 0.00 0.00 0.00 0.00 2.21 06:17:12 PM 2 0.40 0.00 1.20 0.00 0.00 0.00 0.00 0.00 98.40 06:17:12 PM 3 0.81 0.00 0.60 0.00 0.00 0.00 0.00 0.00 98.59 Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle Average: all 0.35 0.00 24.90 0.05 0.00 0.00 0.00 0.00 74.70 Average: 0 0.00 0.00 0.40 0.00 0.00 0.00 0.00 0.00 99.60 Average: 1 0.00 0.00 97.79 0.00 0.00 0.00 0.00 0.00 2.21 Average: 2 0.40 0.00 1.20 0.00 0.00 0.00 0.00 0.00 98.40 Average: 3 0.81 0.00 0.60 0.00 0.00 0.00 0.00 0.00 98.59 Linux 2.6.32-431.el6.x86_64 (localhost.localdomain) 04/27/2020 _x86_64_ (4 CPU) Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util sda 0.00 6.62 0.00 0.28 0.10 55.18 197.39 0.00 16.34 17.61 16.33 2.20 0.06 sdb 0.00 8.30 0.00 0.14 0.09 67.52 466.32 0.00 19.77 11.13 19.87 1.55 0.02 dm-0 0.00 0.00 0.01 15.34 0.19 122.70 8.01 0.03 2.04 22.82 2.03 0.05 0.08 dm-1 0.00 0.00 0.00 0.00 0.00 0.00 8.00 0.00 9.10 9.16 8.86 6.09 0.00
能夠看到結合iostat分析發現致使負載升高的是IO致使系統負載升高
[root@localhost ~]# stress -c 8 --timeout 600 stress: info: [8429] dispatching hogs: 8 cpu, 0 io, 0 vm, 0 hdd
利用stress -c 8 --timeout 600能夠模擬更加複雜的場景
Linux是一個多任務操做系統,它支持遠大於CPU數量的任務同時運行。固然,這些任務實際上並非真的在同時運行,而是由於系統在很短的時間內,將CPU輪流分配給它們,形成多任務同時運行的錯覺。每一個任務運行前,CPU都須要知道任務從哪裏加載,又從哪裏開始運行,也就是說,須要系統事先幫它設置好CPU寄存器和程序計數器。CPU寄存器,是CPU內置的容量小,但速度極快的內存。程序計數器,則是用來存儲CPU正在執行的指令位置,或者即將執行的下一條指令位置。它們都是CPU在運行任務前,必須的依賴環境,所以也被叫作CPU上下文。
CPU上下文切換,就是先把前一個任務的CPU上下文保存起來,而後加載新任務的上下文到這些寄存器和程序計數器,最後再跳轉到程序計數器所指的新位置,運行新任務。而這些保存下來的上下文,會存儲在系統內核中,並在任務從新調度執行時再次加載進來。這樣就能保證任務原來的狀態不受影響,讓任務看起來仍是連續執行。
根據任務的不一樣,CPU的上下文切換就能夠分爲進程上下文切換、線程上下文切換以及中斷上下文切換。
Linux按照特權等級,把進程的運行空間分爲內核空間和用戶空間,分別對應着下圖中,CPU特權等級的Ring0和Ring3。
內核空間(Ring0)具備最高權限,能夠直接訪問全部資源;
用戶空間(Ring3)只能訪問受限資源,不能直接訪問內存等硬件設備,必須經過系統調用陷入到內核中,才能訪問這些特權資源。
也就是說,進程既能夠在用戶空間運行,又能夠在內核空間中運行。進程在用戶空間運行時,被稱爲進程的用戶態,而陷入內核空間的時候,被稱爲進程的內核態。
從用戶態到內核態的轉變,須要經過系統調用來完成。好比,當咱們查看文件內容時,就須要屢次系統調用來完成:首先調用open()打開文件,而後調用read()讀取文件內容,並調用write()將內容寫到標準輸出,最後再調用close()關閉文件。
CPU寄存器裏原來用戶態的指令位置,須要先保存起來。接着,爲了執行內核態代碼,CPU寄存器須要更新爲內核態指令的新位置,最後纔是跳轉到內核態運行內核任務。
而系統調用結束後,CPU寄存器須要恢復原來保存的用戶態,而後在切換到用戶空間,繼續運行進程。因此,一次系統調用的過程,實際上是發生了兩次CPU上下文切換。
不過,須要注意的是,系統調用過程當中,並不會涉及到虛擬內存等進程用戶的資源,也不會切換進程。這與咱們一般所說的進程上下文切換是不同的:
進程上下文切換,是指從一個進程切換到另外一個進程運行。
而系統調用過程當中一直是同一個進程在運行。
因此,系統調用過程一般稱爲特權模式切換,而不是上下文切換。但實際上,系統調用過程當中,CPU的上下文切換仍是沒法避免的。
進程上下文切換跟系統調用的區別:
首先,須要知道,進程是由內核來管理和調度的,進程的切換隻能發生在內核態。因此,進程的上下文不只包括了虛擬內存、棧、全局變量等用戶空間的資源,還包括了內核堆棧、寄存器等內核空間的狀態。
所以,進程上下文切換就比系統調用多了一步:在保存當前進程的內核狀態和CPU寄存器以前,須要先把該進程的虛擬內存、棧等保存下來;而加載了下一進程的內核態後,還須要刷新進程的虛擬內存和用戶棧。
以下圖所示,保存上下文和恢復上下文的過程並非免費的,須要內核在CPU上運行才能完成。
根據研究代表,每次上下文切換都須要幾十納秒到數微秒的CPU時間,這個時間仍是至關可觀的,特別是在進程上下文切換次數較多的狀況下,很容易致使CPU將大量時間耗費在寄存器、內核棧以及虛擬內存等資源的保存和恢復上,進而大大縮短了真正運行進程的時間。這也是致使平均負載上升的一個重要因素。
Linux經過TLB來管理虛擬內存到物理內存的映射關係。當虛擬內存更新後,TLB也須要刷新,內存的訪問也會隨之變慢。特別是在多處理系統上,緩存是被多個處理器共享的,刷新緩存不只會影響當前處理器的進程,還會影響共享緩存的其餘處理器的進程。
顯然,進程切換時才須要切換上下文,換句話說,只有在進程調度的時候,才須要切換上下文。Linux爲每一個CPU都維護了一個就緒隊列,將活躍進程(即正在運行和正在等待CPU的進程)按照優先級和等待CPU的時間排序,而後選擇最須要CPU的進程,這也就是優先級最高和等待CPU時間最長的進程來運行。
觸發進程調度的場景:
爲了保證全部進程能夠獲得公平調度,CPU時間被劃分爲一段段的時間片,這些時間片再被輪流分配給各個進程。這樣,當某個進程的時間片耗盡了,就會被系統掛起,切換到其它正在等待CPU的進程執行。
進程在系統資源不足時,要等到資源知足後才能夠運行,這個時候進程也會被掛起,並由系統調度其它進程運行。
當進程經過睡眠函數sleep這樣的方法將本身主動掛起時,天然也會從新調度。
當有優先級更高的進程運行時,爲了保證高優先級進程的運行,當前進程會被掛起,由高優先級進程來運行。
當發生硬中斷時,CPU上的進程會被掛起,轉而執行內核中的中斷服務程序。
線程與進程最大的區別在於,線程是調度的基本單位,而進程則是資源擁有的基本單位。所謂內核中的任務調度,實際上的調度對象是線程;而進程只是給線程提供了虛擬內存、全局變量等資源。因此,對於線程和進程能夠這麼理解:
當進程只有一個線程時,能夠認爲進程就等於線程。
當進程擁有多個線程時,這些線程會共享相同的虛擬內存和全局變量等資源。這些資源在上下文切換時是不須要修改的。
線程也有本身的私有數據,好比棧和寄存器等,這些在上下文切換時也是須要保存的。
所以,線程的上下文切換其實就能夠分爲兩種狀況:
第一種,先後兩個線程屬於不一樣進程。此時,資源不一樣享,因此切換過程就跟進程上下文切換是同樣的。
第二種,先後兩個線程屬於同一個進程。此時,虛擬內存是共享的,因此在切換時,虛擬內存這些資源就保持不動,只須要切換線程的私有數據、寄存器等不一樣享數據。
經過以上狀況能夠發現,雖然同爲上下文切換,但同進程內的線程切換,要比多進程間切換消耗更少的資源,而這,也正是多線程代替多進程的一個優點。
切換進程CPU上下文,其實就是中斷上下文切換。爲了快速響應硬件的事件,中斷處理會打斷進程的正常調度和執行,轉而調用中斷處理程序,響應設備事件。而在打斷其餘進程時,就須要將進程當前狀態保存下來,這樣在中斷結束後,進程仍然能夠從原來的狀態恢復運行。
跟進程上下文不一樣,中斷上下文切換並不涉及到進程的用戶態。因此,即使中斷過程打斷了一個正處在用戶態的進程,也不須要保存和恢復這個進程的虛擬內存、全局變量等用戶態資源。中斷上下文,其實只包括內核態中斷服務程序執行所必須的狀態,包括CPU寄存器、內核堆棧、硬件中斷參數等。
對同一個CPU來講,中斷處理比進程擁有更高的優先級,因此中斷上下文切換並不會與進程上下文切換同時發生。一樣道理,因爲中斷會打斷正常進程的調度和執行,因此大部分中斷處理程序都短小精悍,以便儘量快的執行結束。
另外,跟進程上下文切換同樣,中斷上下文切換也須要消耗CPU,切換次數過多也會消耗大量的CPU,甚至嚴重下降系統的總體性能。因此,當發現中斷次數過多時,就須要注意去排查它是否會給系統帶來嚴重的性能問題。
利用vmstat工具來進行查看上下文切換,例如:
[root@localhost ~]# vmstat 2 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 384 1303264 215296 12506412 0 0 0 15 0 0 1 1 98 0 0 0 0 384 1303256 215296 12506412 0 0 0 0 237 201 0 0 99 0 0 0 0 384 1303000 215296 12506412 0 0 0 8 290 227 1 1 99 0 0 0 0 384 1302884 215296 12506412 0 0 0 0 227 206 0 1 99 0 0 0 0 384 1302628 215296 12506412 0 0 0 0 250 231 0 1 99 0 0
cs是每秒上下文切換的次數
in則是每秒鐘中斷的次數
r是就緒隊列的長度,也就是正在運行和等待CPU的進程數
b則是出於不可中斷睡眠狀態的進程數
能夠看到,這個例子中的上線文切換次數cs是201次,而系統中斷in則是237次,而就緒隊列長度r和不可中斷狀態進程數b都是0。
vmstat只給出了系統整體的上下文切換狀況,要向查看每一個進程的詳細狀況,就須要使用到pidstat了,以下:
[root@localhost ~]# pidstat -w 5 Linux 2.6.32-431.el6.x86_64 (localhost.localdomain) 04/29/2020 _x86_64_ (4 CPU) 05:00:25 PM PID cswch/s nvcswch/s Command 05:00:30 PM 3 0.20 0.00 migration/0 05:00:30 PM 4 0.20 0.00 ksoftirqd/0 05:00:30 PM 7 0.40 0.00 migration/1 05:00:30 PM 9 0.20 0.00 ksoftirqd/1 05:00:30 PM 13 0.20 0.00 ksoftirqd/2 05:00:30 PM 15 0.60 0.00 migration/3 05:00:30 PM 17 2.40 0.00 ksoftirqd/3 05:00:30 PM 19 1.20 0.00 events/0 05:00:30 PM 20 1.00 0.00 events/1 05:00:30 PM 21 1.00 0.00 events/2 05:00:30 PM 22 1.00 0.00 events/3 05:00:30 PM 28 0.20 0.00 sync_supers 05:00:30 PM 29 0.20 0.00 bdi-default 05:00:30 PM 197 1.00 0.00 mpt_poll_0 05:00:30 PM 353 0.20 0.00 flush-253:0 05:00:30 PM 598 1.00 0.00 vmmemctl 05:00:30 PM 1202 0.40 0.00 master 05:00:30 PM 1231 1.00 0.00 zabbix_agentd 05:00:30 PM 1235 1.00 0.00 zabbix_agentd 05:00:30 PM 2912 2.00 0.00 bash 05:00:30 PM 3360 10.98 0.00 redis-server 05:00:30 PM 3748 1.00 0.20 python 05:00:30 PM 5830 0.40 0.00 showq 05:00:30 PM 5883 0.20 0.00 pidstat 05:00:30 PM 29194 1.00 1.60 apps.plugin
這個結果中有兩列內容是咱們重點關注的對象。一個是cswch,表示每秒自願上下文切換的次數,另外一個則是mbcswch,表示每秒非自願上下文切換的次數。
這兩個概念意味着不一樣的性能問題:
自願上下文切換,是指進程沒法獲取所需自願,致使上下文切換。好比,IO、內存等系統資源不足時,就會發生自願上下文切換。
非自願上下文切換,則是指進程因爲時間片已到等緣由,被系統強制調度,進而發生的上下文切換。好比說,大量進程都在爭搶CPU時,就容易發生非自願上下文切換。
使用sysbench來模擬系統多線程調度切換的狀況。
sysbench是一個多線程的基準測試工具,通常用來評估不一樣系統參數下的數據庫負載狀況,能夠用來模擬上下文切換過多的問題。
測試前的數據查看狀況
[root@localhost ~]# vmstat 1 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 384 1302564 215296 12506416 0 0 0 15 0 0 1 1 98 0 0 0 0 384 1302556 215296 12506416 0 0 0 0 257 207 1 1 99 0 0 0 0 384 1302556 215296 12506416 0 0 0 0 223 192 1 1 99 0 0 0 0 384 1302440 215296 12506416 0 0 0 0 257 219 1 1 99 0 0 0 0 384 1302176 215296 12506416 0 0 0 4 248 225 0 0 99 0 0 0 0 384 1302176 215296 12506416 0 0 0 0 218 203 1 1 99 0 0 0 0 384 1303044 215296 12506416 0 0 0 0 371 239 1 1 98 0 0 0 0 384 1302804 215296 12506416 0 0 0 0 232 213 0 1 99 0 0
在終端離運行sysbench,模擬系統多線程調度的瓶頸:
[root@localhost ~]# sysbench --threads=10 --max-time=300 threads run WARNING: --max-time is deprecated, use --time instead sysbench 1.0.17 (using system LuaJIT 2.0.4) Running the test with following options: Number of threads: 10 Initializing random number generator from current time Initializing worker threads... Threads started!
執行sysbench後,使用vmstat來進行監控:
[root@localhost ~]# vmstat 2 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 384 1297912 215400 12509840 0 0 0 15 0 0 1 1 98 0 0 2 0 384 1298036 215400 12509840 0 0 0 10 279 214 1 1 99 0 0 1 0 384 1298052 215400 12509840 0 0 0 0 241 202 1 1 99 0 0 8 0 384 1296716 215400 12509840 0 0 0 0 7069 257920 3 39 57 0 0 8 0 384 1296468 215400 12509840 0 0 0 0 17640 477390 7 80 13 0 0 10 0 384 1295592 215400 12509840 0 0 0 0 18891 657740 6 85 9 0 0 8 0 384 1295724 215400 12509840 0 0 0 0 19504 597917 7 82 11 0 0
觀測數據能夠發現:
r列:就緒隊列的長度已經到8,遠遠超過了系統CPU的個數2,因此確定會有大量的CPU競爭。
us和sy列:這兩列的CPU使用率加起來上升到了100%,其中系統CPU使用率,也就是sy列高達80%左右,說明CPU主要是被內核佔用了。
in列:中斷次數也上升到了將近2萬左右,說明中斷處理也是個潛在的問題。
vmstat詳解以下:
綜合這幾個指標,能夠知道,系統的就緒隊列過長,也就是正在運行和等待CPU的進程數過多,致使了大量的上下文切換,而上下文切換又致使了系統CPU的佔用率升高。
[root@localhost ~]# pidstat -w -u 1 Linux 2.6.32-431.el6.x86_64 (localhost.localdomain) 04/29/2020 _x86_64_ (4 CPU) 05:25:40 PM PID %usr %system %guest %CPU CPU Command 05:25:41 PM 17 0.00 0.98 0.00 0.98 3 ksoftirqd/3 05:25:41 PM 3360 0.98 0.98 0.00 1.96 1 redis-server 05:25:41 PM 3723 1.96 0.98 0.00 2.94 1 netdata 05:25:41 PM 7661 28.43 100.00 0.00 100.00 1 sysbench 05:25:41 PM 7698 0.00 0.98 0.00 0.98 3 pidstat 05:25:41 PM 29194 0.98 0.98 0.00 1.96 1 apps.plugin 05:25:40 PM PID cswch/s nvcswch/s Command 05:25:41 PM 4 7.84 0.00 ksoftirqd/0 05:25:41 PM 9 1.96 0.00 ksoftirqd/1 05:25:41 PM 13 10.78 0.00 ksoftirqd/2 05:25:41 PM 17 10.78 0.00 ksoftirqd/3 05:25:41 PM 19 0.98 0.00 events/0 05:25:41 PM 20 0.98 0.00 events/1 05:25:41 PM 21 0.98 0.00 events/2 05:25:41 PM 22 0.98 0.00 events/3 05:25:41 PM 29 0.98 0.00 bdi-default 05:25:41 PM 61 0.98 0.00 khugepaged 05:25:41 PM 197 0.98 0.00 mpt_poll_0 05:25:41 PM 598 0.98 0.00 vmmemctl 05:25:41 PM 1231 0.98 0.00 zabbix_agentd 05:25:41 PM 1235 0.98 0.00 zabbix_agentd 05:25:41 PM 3360 10.78 0.00 redis-server 05:25:41 PM 3748 0.98 116.67 python 05:25:41 PM 7109 2.94 78.43 bash 05:25:41 PM 7698 0.98 1.96 pidstat 05:25:41 PM 29194 0.98 313.73 apps.plugin
從pidstat的輸出能夠發現,CPU使用率的升高是因爲sysbench致使的,它的CPU使用率已經達到了100%,但上下文切換則是來自其餘進程,包括自願上下文切換頻率較高的redis-server和內核進程ksoftirqd/二、ksoftirqd/3,以及非自願上下文切換頻率比較高的python和apps.plugnin。
因爲Linux調度的最小單位是線程,而sysbench模擬的也是線程的調度問題,所以vmstat顯示的中斷次數遠大於pidstat中顯示的次數,在pidstat後面加上選項-t,對線程進行監控:以下
[root@localhost ~]# pidstat -w -t -u 1 Linux 2.6.32-431.el6.x86_64 (localhost.localdomain) 04/29/2020 _x86_64_ (4 CPU) 06:05:28 PM TGID TID %usr %system %guest %CPU CPU Command 06:05:29 PM 13 - 0.00 0.97 0.00 0.97 2 ksoftirqd/2 06:05:29 PM - 13 0.00 0.97 0.00 0.97 2 |__ksoftirqd/2 06:05:29 PM - 3726 0.00 0.97 0.00 0.97 1 |__netdata 06:05:29 PM - 3738 0.00 0.97 0.00 0.97 2 |__netdata 06:05:29 PM - 4020 0.00 0.97 0.00 0.97 0 |__python 06:05:29 PM 10405 - 33.98 100.00 0.00 100.00 1 sysbench 06:05:29 PM - 10406 4.85 36.89 0.00 41.75 1 |__sysbench 06:05:29 PM - 10407 2.91 31.07 0.00 33.98 2 |__sysbench 06:05:29 PM - 10408 2.91 33.01 0.00 35.92 2 |__sysbench 06:05:29 PM - 10409 2.91 33.98 0.00 36.89 2 |__sysbench 06:05:29 PM - 10410 3.88 33.98 0.00 37.86 3 |__sysbench 06:05:29 PM - 10411 3.88 33.01 0.00 36.89 2 |__sysbench 06:05:29 PM - 10412 1.94 31.07 0.00 33.01 2 |__sysbench 06:05:29 PM - 10413 4.85 33.01 0.00 37.86 3 |__sysbench 06:05:29 PM - 10414 2.91 33.01 0.00 35.92 1 |__sysbench 06:05:29 PM - 10415 3.88 34.95 0.00 38.83 0 |__sysbench 06:05:29 PM 10428 - 0.97 1.94 0.00 2.91 0 pidstat 06:05:29 PM - 10428 0.97 1.94 0.00 2.91 0 |__pidstat 06:05:29 PM 29194 - 0.00 0.97 0.00 0.97 2 apps.plugin 06:05:29 PM - 29194 0.00 0.97 0.00 0.97 2 |__apps.plugin 06:05:28 PM TGID TID cswch/s nvcswch/s Command 06:05:29 PM 4 - 9.71 0.00 ksoftirqd/0 06:05:29 PM - 4 9.71 0.00 |__ksoftirqd/0 06:05:29 PM 9 - 7.77 0.00 ksoftirqd/1 06:05:29 PM - 9 7.77 0.00 |__ksoftirqd/1 06:05:29 PM 13 - 7.77 0.00 ksoftirqd/2 06:05:29 PM - 13 7.77 0.00 |__ksoftirqd/2 06:05:29 PM 17 - 15.53 0.00 ksoftirqd/3 06:05:29 PM - 17 15.53 0.00 |__ksoftirqd/3 06:05:29 PM 19 - 0.97 0.00 events/0 06:05:29 PM - 19 0.97 0.00 |__events/0 06:05:29 PM 20 - 0.97 0.00 events/1 06:05:29 PM - 20 0.97 0.00 |__events/1 06:05:29 PM 21 - 0.97 0.00 events/2 06:05:29 PM - 21 0.97 0.00 |__events/2 06:05:29 PM 22 - 0.97 0.00 events/3 06:05:29 PM - 22 0.97 0.00 |__events/3 06:05:29 PM 28 - 0.97 0.00 sync_supers 06:05:29 PM - 28 0.97 0.00 |__sync_supers 06:05:29 PM 197 - 0.97 0.00 mpt_poll_0 06:05:29 PM - 197 0.97 0.00 |__mpt_poll_0 06:05:29 PM 598 - 0.97 0.00 vmmemctl 06:05:29 PM - 598 0.97 0.00 |__vmmemctl 06:05:29 PM 1202 - 0.97 0.00 master 06:05:29 PM - 1202 0.97 0.00 |__master 06:05:29 PM 1231 - 0.97 0.00 zabbix_agentd 06:05:29 PM - 1231 0.97 0.00 |__zabbix_agentd 06:05:29 PM 1235 - 1.94 0.00 zabbix_agentd 06:05:29 PM - 1235 1.94 0.00 |__zabbix_agentd 06:05:29 PM 3360 - 10.68 0.00 redis-server 06:05:29 PM - 3360 10.68 0.00 |__redis-server 06:05:29 PM - 3725 0.97 31.07 |__netdata 06:05:29 PM - 3726 0.97 0.00 |__netdata 06:05:29 PM - 3727 0.97 0.00 |__netdata 06:05:29 PM - 3728 2.91 0.00 |__netdata 06:05:29 PM - 3729 49.51 2.91 |__netdata 06:05:29 PM - 3730 0.97 0.00 |__netdata 06:05:29 PM - 3733 0.97 0.00 |__netdata 06:05:29 PM - 3738 0.97 87.38 |__netdata 06:05:29 PM - 3740 1.94 0.00 |__netdata 06:05:29 PM - 3743 0.97 0.00 |__netdata 06:05:29 PM - 3744 0.97 0.00 |__netdata 06:05:29 PM - 3745 0.97 0.00 |__netdata 06:05:29 PM - 3751 0.97 0.00 |__netdata 06:05:29 PM 3748 - 0.97 0.00 python 06:05:29 PM - 3748 0.97 0.00 |__python 06:05:29 PM - 4020 3.88 6.80 |__python 06:05:29 PM - 4021 3.88 2.91 |__python 06:05:29 PM 7109 - 0.97 52.43 bash 06:05:29 PM - 7109 0.97 52.43 |__bash 06:05:29 PM 9337 - 1.94 0.00 showq 06:05:29 PM - 9337 1.94 0.00 |__showq 06:05:29 PM - 10406 18642.72 45331.07 |__sysbench 06:05:29 PM - 10407 20953.40 42127.18 |__sysbench 06:05:29 PM - 10408 17404.85 44594.17 |__sysbench 06:05:29 PM - 10409 18404.85 45963.11 |__sysbench 06:05:29 PM - 10410 12807.77 61773.79 |__sysbench 06:05:29 PM - 10411 19445.63 38708.74 |__sysbench 06:05:29 PM - 10412 17883.50 40695.15 |__sysbench 06:05:29 PM - 10413 17189.32 49639.81 |__sysbench 06:05:29 PM - 10414 18169.90 45739.81 |__sysbench 06:05:29 PM - 10415 14832.04 47845.63 |__sysbench 06:05:29 PM 10428 - 0.97 96.12 pidstat 06:05:29 PM - 10428 0.97 96.12 |__pidstat 06:05:29 PM - 21200 1.94 0.00 |__grafana-server 06:05:29 PM - 21202 0.97 0.00 |__grafana-server 06:05:29 PM - 21206 1.94 0.00 |__grafana-server 06:05:29 PM - 21209 0.97 0.00 |__grafana-server 06:05:29 PM - 25021 1.94 0.00 |__grafana-server 06:05:29 PM 29194 - 0.97 150.49 apps.plugin 06:05:29 PM - 29194 0.97 150.49 |__apps.plugin
能夠看到sysbench進程的上下文切換看起來並很少,可是sysbench的子線程的上下文切換次數卻不少,咱們發現進程的上下文切換髮生不少同時中斷次數也上升到將近2萬,具體是什麼類型的中斷上升還須要繼續進行監測。
因爲中斷髮生在內核態,而pidstat只是一個進程的性能分析工具,所以他並不能提供任何關於中斷的詳細信息。所以須要從/proc/interrupts這個只讀文件中讀取。/proc其實是Linux的一個虛擬文件系統,用於內核空間與用戶空間之間的通訊。/proc/interrupts就是這種通訊機制的一部分,提供了一個只讀的中斷使用狀況。
[root@localhost ~]# watch -d cat /proc/interrupts [root@localhost ~]# cat /proc/interrupts CPU0 CPU1 CPU2 CPU3 0: 117486 0 0 0 IO-APIC-edge timer 1: 7 0 0 1 IO-APIC-edge i8042 7: 0 0 0 0 IO-APIC-edge parport0 8: 1 0 0 0 IO-APIC-edge rtc0 9: 0 0 0 0 IO-APIC-fasteoi acpi 12: 108 1 0 0 IO-APIC-edge i8042 14: 0 0 0 0 IO-APIC-edge ata_piix 15: 13 17 19 27 IO-APIC-edge ata_piix 17: 3128770 3092486 3307137 3143451 IO-APIC-fasteoi ioc0 24: 0 0 0 0 PCI-MSI-edge pciehp 25: 0 0 0 0 PCI-MSI-edge pciehp 26: 0 0 0 0 PCI-MSI-edge pciehp 27: 0 0 0 0 PCI-MSI-edge pciehp 28: 0 0 0 0 PCI-MSI-edge pciehp 29: 0 0 0 0 PCI-MSI-edge pciehp 30: 0 0 0 0 PCI-MSI-edge pciehp 31: 0 0 0 0 PCI-MSI-edge pciehp 32: 0 0 0 0 PCI-MSI-edge pciehp 33: 0 0 0 0 PCI-MSI-edge pciehp 34: 0 0 0 0 PCI-MSI-edge pciehp 35: 0 0 0 0 PCI-MSI-edge pciehp 36: 0 0 0 0 PCI-MSI-edge pciehp 37: 0 0 0 0 PCI-MSI-edge pciehp 38: 0 0 0 0 PCI-MSI-edge pciehp 39: 0 0 0 0 PCI-MSI-edge pciehp 40: 0 0 0 0 PCI-MSI-edge pciehp 41: 0 0 0 0 PCI-MSI-edge pciehp 42: 0 0 0 0 PCI-MSI-edge pciehp 43: 0 0 0 0 PCI-MSI-edge pciehp 44: 0 0 0 0 PCI-MSI-edge pciehp 45: 0 0 0 0 PCI-MSI-edge pciehp 46: 0 0 0 0 PCI-MSI-edge pciehp 47: 0 0 0 0 PCI-MSI-edge pciehp 48: 0 0 0 0 PCI-MSI-edge pciehp 49: 0 0 0 0 PCI-MSI-edge pciehp 50: 0 0 0 0 PCI-MSI-edge pciehp 51: 0 0 0 0 PCI-MSI-edge pciehp 52: 0 0 0 0 PCI-MSI-edge pciehp 53: 0 0 0 0 PCI-MSI-edge pciehp 54: 0 0 0 0 PCI-MSI-edge pciehp 55: 0 0 0 0 PCI-MSI-edge pciehp 56: 12676123 621337444 15964441 14094017 PCI-MSI-edge eth0-rxtx-0 57: 12934876 27740827 549375875 13481933 PCI-MSI-edge eth0-rxtx-1 58: 12958840 27092299 22935606 555653407 PCI-MSI-edge eth0-rxtx-2 59: 533414281 24804405 22861636 20169043 PCI-MSI-edge eth0-rxtx-3 60: 0 0 0 0 PCI-MSI-edge eth0-event-4 NMI: 0 0 0 0 Non-maskable interrupts LOC: 3073899782 2932109969 2836889656 2806862212 Local timer interrupts SPU: 0 0 0 0 Spurious interrupts PMI: 0 0 0 0 Performance monitoring interrupts IWI: 18 16 18 15 IRQ work interrupts RES: 486603569 505967773 471350449 492621309 Rescheduling interrupts CAL: 75258 1646 73324 1735 Function call interrupts TLB: 33950017 55405448 32837754 52628068 TLB shootdowns TRM: 0 0 0 0 Thermal event interrupts THR: 0 0 0 0 Threshold APIC interrupts MCE: 0 0 0 0 Machine check exceptions MCP: 117332 117332 117332 117332 Machine check polls ERR: 0 MIS: 0
經過觀察發現,變化速度最快的是重調度中斷RES,這個中斷類型表示,喚醒空閒狀態的CPU來調度薪的任務運行,這是多處理器系統中,調度器用來分散任務導不一樣CPU的機制,一般也被稱爲處理器間中斷
因此,這裏的中斷升高仍是由於過多任務的調度問題,跟前面上下文切換次數的分析結果是一致的。
上下文切換正常的數值取決於系統自己的CPU性能。若是系統的上下文切換次數比較穩定,那麼從數百到1萬之內,都應該算是正常。當上下文切換次數超過一萬次,或者切換次數出現數量級的增加時,就頗有可能出現了性能問題。
這個時候須要依據上下文切換的類型,在作具體分析:
自願上下文切換變多了,說明進程都在等待自願,有可能發生了IO等其餘問題;
非自願上下文切換變多了,說明進程都在被強制調度,也就是都在爭搶CPU,說明CPU的確成了瓶頸;
中斷次數變多了,說明CPU被中斷處理程序佔用了,還須要經過查看/proc/interrupts文件來分析具體的中斷類型
Linux做爲一個多任務操做系統,將每一個CPU的時間劃分爲很短的時間片,再經過調度器輪流分配給各個任務使用,所以形成多任務同時運行的錯覺。
爲了維護CPU時間,Linux經過事先定義的節拍率(內核中表示爲HZ),觸發時間中斷,並使用全局變量Jiffies記錄了開機以來的節拍數。每發生一次時間中斷,Jiffies的值就加1。
節拍率HZ是內核的可配選項,能夠配置爲100、250、1000等。不一樣的系統可能設置不一樣的數值,能夠經過查詢/boot/config內核選項來查看它的配置(CONFIG_HZ=1000)。好比在個人服務器系統中,節拍率設置成了1000,也就是每秒鐘觸發1000次時間中斷。
[root@localhost ~]# grep 'CONFIG_HZ=' /boot/config-2.6.32-431.el6.x86_64 CONFIG_HZ=1000
正由於節拍率HZ是內核選項,因此用戶空間程序並不能直接訪問。爲了方便用戶空間程序,內核還提供了一個用戶空間節拍率USER_HZ,它老是固定爲100,也就是1/100秒。這樣,用戶空間程序並不須要關心內核中HZ被設置成了多少,由於它看到的老是固定值USER_HZ。
Linux經過/proc虛擬文件系統,向用戶空間提供了系統內部狀態的信息,而/proc/stat提供的就是系統的CPU和任務統計信息。若是隻須要關注CPU,能夠執行以下命令:
[root@localhost ~]# cat /proc/stat |grep ^cpu cpu 182993898 729 117810616 13772680802 1631791 13585 2713967 0 0 cpu0 44712915 43 27980485 3442961333 378691 3216 649777 0 0 cpu1 45582701 297 30219438 3442511274 419280 3848 738211 0 0 cpu2 46830450 48 28005111 3445732783 420358 3273 676506 0 0 cpu3 45867831 339 31605580 3441475411 413462 3246 649470 0 0
這裏輸出結果是一個表格。其中,第一列表示的是CPU編號,如cpu0、cpu一、cpu二、cpu3,而第一行沒有編號的cpu,表示的是全部CPU的累加。而其餘列表示不一樣場景下CPU的累加節拍數,她的單位是USER_HZ,也就是10ms(1/100秒),因此這其實就是不一樣場景下的CPU時間。
user(一般縮寫爲us),表明用戶態CPU時間。注意,它不包含下面的nice時間,但包括了gust時間。
nice(一般縮寫爲ni),表明低級優先級用戶態CPU時間,也就是進程的nice值被調整爲1-19之間的CPU時間,這裏注意nice可取值範圍是-20到19,數值越大,優先級反而越低。
system(一般縮寫爲sys),表明內核態CPU時間。
idle(一般縮寫爲id),表明空閒時間。注意,它不包括等待IO的時間(iowait)。
iowait(一般縮寫爲wa),表明等待IO的CPU時間。
irq(一般縮寫爲hi),表明處理硬中斷的CPU時間。
softirq(一般縮寫爲si),表明處理軟中斷的CPU時間。
steal(一般縮寫爲st),表明當系統運行在虛擬機中的時候,被其餘虛擬機佔用的CPU時間。
guest(一般縮寫爲guest),表明經過虛擬化運行其餘操做系統的時間,也就是運行虛擬機的CPU時間、
guest_nice(一般縮寫爲gnice),表明低優先級運行虛擬機的時間。
一般所說的CPU使用率,就是除了空閒時間外的其餘時間佔用CPU時間的百分比,用公式表示就是
根據這個公式,咱們就能夠從/proc/stat中的數據,很容易地計算出CPU使用率。固然,也能夠用每個場景的CPU時間,除以總的CPU時間,計算出每一個場景的CPU使用率。
查看/proc/stat中的數據,顯示的是開機以來的節拍數累加值,因此直接算出來的,是開機以來的平均CPU使用率,通常沒有什麼參考價值。
事實上,爲了計算CPU使用率,性能工具通常都會間隔一段時間的兩次值,做差後,再計算出這段時間內平均CPU使用率。
這個公式,就是咱們用各類性能工具所看到的CPU使用率的實際計算方法。
進程的CPU使用率方法與系統指標相似,Linux也給每一個進程提供了運行狀況的統計信息,也就是/proc/[pid]/stat。不過,這個文件包含的數據就比較豐富了,總共有52列的數據。
性能分析工具給出的都是間隔一段時間的平均CPU使用率,因此要注意間隔時間的設置,特別是用多個工具對比分析時,你必定要保證他們用的是相同的間隔時間。
好比,對比一下top和ps這兩個工具報告的CPU使用率,默認的結果極可能不同,由於top默認使用3秒時間間隔,而ps使用的倒是進程的整個生命週期。
top和ps是最經常使用的性能分析工具:
top顯示了系統整體的CPU和內存使用狀況,以及各個進程的資源使用狀況。
ps則只顯示了每一個進程的資源使用狀況。
關於top命令使用見下圖詳解
top命令每一個進程都有一個%CPU列,表示進程的CPU使用率。它是用戶態和內核態CPU使用率的總和,包括進程用戶空間使用的CPU、經過系統調用執行的內核空間CPU、以及在就緒隊列等待運行的CPU。在虛擬化環境中,它還包括了運行虛擬機佔用的CPU,能夠發現top命令並無細分進程的用戶態CPU和內核態CPU。
若是想要查看進程CPU使用率的具體狀況須要使用pidstat命令來進行觀測;
[root@localhost ~]# pidstat 1 5 Linux 2.6.32-431.el6.x86_64 (localhost.localdomain) 04/30/2020 _x86_64_ (4 CPU) 02:29:12 PM PID %usr %system %guest %CPU CPU Command 02:29:13 PM 14734 0.00 0.98 0.00 0.98 3 apps.plugin 02:29:13 PM 29918 0.98 0.98 0.00 1.96 1 pidstat 02:29:13 PM PID %usr %system %guest %CPU CPU Command 02:29:14 PM 3360 0.00 1.00 0.00 1.00 0 redis-server 02:29:14 PM 3723 1.00 0.00 0.00 1.00 0 netdata 02:29:14 PM 14734 1.00 0.00 0.00 1.00 3 apps.plugin 02:29:14 PM 21198 1.00 0.00 0.00 1.00 1 grafana-server 02:29:14 PM 29167 0.00 1.00 0.00 1.00 2 bash 02:29:14 PM 29918 0.00 1.00 0.00 1.00 1 pidstat 02:29:14 PM PID %usr %system %guest %CPU CPU Command 02:29:15 PM 3748 1.00 0.00 0.00 1.00 0 python 02:29:15 PM 14734 0.00 1.00 0.00 1.00 3 apps.plugin 02:29:15 PM 29918 0.00 1.00 0.00 1.00 1 pidstat 02:29:15 PM PID %usr %system %guest %CPU CPU Command 02:29:16 PM 3723 1.00 0.00 0.00 1.00 0 netdata 02:29:16 PM 14734 0.00 1.00 0.00 1.00 3 apps.plugin 02:29:16 PM 21198 0.00 1.00 0.00 1.00 1 grafana-server 02:29:16 PM 29167 1.00 0.00 0.00 1.00 1 bash 02:29:16 PM 29918 1.00 0.00 0.00 1.00 1 pidstat 02:29:16 PM PID %usr %system %guest %CPU CPU Command 02:29:17 PM 3360 1.00 0.00 0.00 1.00 0 redis-server 02:29:17 PM 3723 1.00 1.00 0.00 2.00 0 netdata 02:29:17 PM 14734 1.00 0.00 0.00 1.00 3 apps.plugin 02:29:17 PM 29918 0.00 1.00 0.00 1.00 1 pidstat Average: PID %usr %system %guest %CPU CPU Command Average: 3360 0.20 0.20 0.00 0.40 - redis-server Average: 3723 0.60 0.20 0.00 0.80 - netdata Average: 3748 0.20 0.00 0.00 0.20 - python Average: 14734 0.40 0.60 0.00 1.00 - apps.plugin Average: 21198 0.20 0.20 0.00 0.40 - grafana-server Average: 29167 0.20 0.20 0.00 0.40 - bash Average: 29918 0.40 0.80 0.00 1.20 - pidstat
如上面的pidstat命令,就間隔1秒展現了進程的5組CPU使用率,包括
用戶態CPU使用率(%usr)
內核態CPU使用率(%system);
運行虛擬機CPU使用率(%guest);
等待CPU使用率(%wait);
以及總的CPU使用率(%CPU)
最後Average部分,還計算了5組數據的平均值。
perf是Linux2.6.31之後內置的性能分析工具,它以性能時間採樣爲基礎,不只能夠分析系統的各類事件和內核性能,還能夠用來分析指定應用程序的性能問題。
[root@localhost ~]# perf top Samples: 11K of event 'cpu-clock', Event count (approx.):1015 Overhead Shared Object Symbol 9.42% [kernel] [k] kallsyms_expand_symbol 7.03% perf [.] symbols__insert 6.37% perf [.] rb_next 4.51% [kernel] [k] vsnprintf 4.11% [kernel] [k] format_decode 3.71% [kernel] [k] number 3.45% [kernel] [k] strnlen 2.79% [kernel] [k] string 2.52% perf [.] hex2u64 2.12% libc-2.14.so [.] __strcmp_sse42 1.99% libc-2.14.so [.] __memcpy_sse2 1.86% libc-2.14.so [.] _int_malloc 1.59% libc-2.14.so [.] _IO_getdelim 1.59% libc-2.14.so [.] __strchr_sse42 1.46% libc-2.14.so [.] __libc_calloc 1.33% libc-2.14.so [.] __strstr_sse42 1.19% [kernel] [k] get_task_cred 1.19% [kernel] [k] update_iter 1.06% [kernel] [k] module_get_kallsym 1.06% libpthread-2.14.so [.] pthread_rwlock_rdlock
輸出結果中,第一行包含三個數據,分別是採樣數(Sample)、事件類型(event)和事件總數量(Event count)。例子中,pref總共採集了11K個CPU時鐘事件,須要注意若是採樣數過少,那下面的排序和百分比就沒什麼實際參考價值。
第一列Overhead,是該符號的性能事情在全部採用中的比例,用百分比來表示。
第二列Shared,是該函數或指令所在的動態共享對象,如內核、進程名、動態連接庫名、內核模塊名等。
第三列Object,是動態共享對象的類型。好比[.]表示用戶空間的可執行程序、或者動態連接庫,而[k]則表示內核空間。
最後一列Symbol是符號名,也就是函數名。當函數名未知時,用十六進制的地址來表示。
從上面數據,能夠看到,佔用CPU時鐘最多的是kernel(內核),不過它的比例也只有9.42%,說明系統並無CPU性能問題。
參考ps命令詳解,這裏再也不多說