Linux Performance Analysis and Tools(Linux性能分析和工具)


首先來看一張圖:

上面這張神一樣的圖出自國外一個Lead Performance Engineer(Brendan Gregg)的一次分享,幾乎涵蓋了一個系統的方方面面,任何人,如果沒有完善的計算系統知識,網絡知識和操作系統的知識,這張圖中列出的工具,是不可能全部掌握的。

出於本人對linux系統的極大興趣,以及對底層知識的強烈渴望,並作為檢驗自己基礎知識的一個指標,我決定將這里的所有工具學習一遍(時間不限),這篇文章將作為我學習這些工具的學習筆記。盡量組織得方便自己日后查閱,並希望對別人也有一定幫助。

這里所有的工具,都可以通過man 獲得它的幫助文檔,這里只介紹一些常規用法。

注意:文中所有的interval都是指收集數據的間隔時間,times是指采樣次數。例如

vmstat interval times

將命令中的interval和times替換成數字:

vmstat 3 5

上面語句的意思就是每3秒中輸出一次內存統計數據,共輸出5次。

Tools: Basic & Intermediate

  1. uptime
  2. top
  3. htop
  4. mpstat
  5. iostat
  6. vmstat
  7. dstat
  8. netstat
  9. strace
  10. iotop
  11. pidstat
  12. ps
  13. lsof

#vmstat

我們先看一個vmstat 的例子。用下面的命令讓它每5秒中打印一個報告。

可以用ctrl+c停止vmstat。vmstat的常規用法是vmstat interval times,即每隔interval秒采 樣一次,共采樣times次,如果省略times,則一直采集數據到用戶手動停止。

第一行的值是顯示了自系統啟動以來的平均值,第二行開始展示現在正在發生的情況,接下來的行會顯示每5秒的間隔內發生了什么。每一列的含義在頭部,如下所示:

  • procs

r這一列顯示了多少進程正在等待cpu,b列顯示多少進程正在不可中斷的休眠(通常意味着它們在等待IO ,例如磁盤,網絡,用戶輸入,等等)。

  • memory

swapd列顯示了多少塊被換出到了磁盤(頁面交換)。剩下的三個列顯示了多少塊是空閑的(未被使用),多少塊正在被用作緩沖區,以及多少正在被用作操作系統的緩存。

  • swap

這些列顯示頁面交換活動:每秒有多少塊正在被換入(從磁盤)和換出(到磁盤)。它們比監控swpd列重要多了。<font color=#FF0000>大部分時間我們希望看到si 和so 列是0,並且我們很明確不希望看到每秒超過10個塊</font>。

  • io

這些列顯示了多少塊從塊設備讀取(bi)和寫出(bo)。這通常反映了硬盤I/O。

  • system

這些列顯示了每秒中斷(in)和上下文切換(cs)的數量。<font color=#FF0000>除非上下文切換超過100 000次或更多,一般不用擔心上下文切換。</font>

  • cpu

這些列顯示所有的CPU時間花費在各類操作的百分比,包括執行用戶代碼(非內核),執行系統代碼(內核),空閑以及等待IO。如果正在使用虛擬化,第5列可能是st,顯示了從虛擬機中”偷走”的百分比。

內存不足的表現:free memory 急劇減少,回收buffer和cache也無濟於事,大量使用交換分區(swpd),頁面交換(swap)頻繁,讀寫磁盤數量(io)增多,缺頁中斷(in)增多,上下文切換(cs)次數增多,等待IO的進程數(b)增多,大量CPU時間用於等待IO(wa)。

#iostat

現在讓我們轉移到iostat 。默認情況下,它顯示了與vmstat 相同的CPU 使用信息。我們通常只對I/O統計感興趣,所以使用下面的命令只展示擴展的設備統計。

與vmstat一樣,第一行報告顯示的是自系統啟動以來的平均值,(通常刪掉它節省空間),然后接下來的報告顯示了增量的平均值,每個設備一行。

有多種選項顯示和隱藏列。官方文檔有點難以理解,因此我們必須從源碼中挖掘真正顯示的內容是什么。說明的列信息如下:

為了看懂Linux的磁盤IO指標,先了解一些常見的縮寫習慣:rq是request,r是read,w是write,qu是queue,sz是size的,a是average,tm是time,svc是service。

  • rrqm/s 和 wrqm/s

    每秒合並的讀和寫請求。”合並的”意味着操作系統從隊列中拿出多個邏輯請求合並為一個請求到實際磁盤。

  • r/s 和 w/s

    每秒發送到設備的讀和寫請求數。

  • rsec/s 和 wsec/s

    每秒讀和寫的扇區數。有些系統也輸出為rKB/s和wKB/s ,意味每秒讀寫的千字節數。(iostat -dkx interval times)

  • avgrq-sz

    請求的扇區數。(讀扇區數 + 寫扇區數) / (讀請求次數 + 寫請求次數)

  • avgqu-sz

    在設備隊列中等待的請求數。即隊列的平均長度。

  • await

    每個IO請求花費的時間,包括在隊列中的等待時間和實際請求(服務)時間。

  • svctm

    實際請求(服務)時間,以毫秒為單位,不包括排隊時間。

  • %util

    至少有一個活躍請求所占時間的百分比。更好的說法應該是,服務時間所占的百分比。以上面的輸出為例。 一秒中內,讀了2.5次,寫了1.8次,每次請求的實際請求時間(不包括排隊時間)為6.0ms,那么總的時間花費為(2.5+1.8)*6.0ms,即25.8ms,0.0258秒,轉換成百分比再四舍五入就得到了util的值2.6%。

    %util: When this figure is consistently approaching above 80% you will need to take any of the following actions - * increasing RAM so dependence on disk reduces * increasing RAID controller cache so disk dependence decreases * increasing number of disks so disk throughput increases (more spindles working parallely) * horizontal partitioning

下面這個公式可以計算一個請求在整個請求期間,有多少時間用以等待。當這個值大於50%,說明整個請求期間,花費了更多時間在隊列中等待;如果這個數很大,則應該采取相應措施。

  • (await-svctim)/await*100: The percentage of time that IO operations spent waiting in queue in comparison to actually being serviced. If this figure goes above 50% then each IO request is spending more time waiting in queue than being processed. If this ratio skews heavily upwards (in the >75% range) you know that your disk subsystem is not being able to keep up with the IO requests and most IO requests are spending a lot of time waiting in queue. In this scenario you will again need to take any of the actions above

IO瓶頸的症狀: 1. %util 很高 2. await 遠大於svctm 3. avgqu-sz 比較大

下面解釋了iowait的作用,需要注意的是,高速CPU也可能導致iowait取值較大。

  • %iowait: This number shows the % of time the CPU is wasting in waiting for IO. A part of this number can result from network IO, which can be avoided by using an Async IO library. The rest of it is simply an indication of how IO-bound your application is. You can reduce this number by ensuring that disk IO operations take less time, more data is available in RAM, increasing disk throughput by increasing number of disks in a RAID array, using SSD (Check my post on Solid State drives vs Hard Drives) for portions of the data or all of the data etc

上面的解釋主要參考《高性能mysql》和這篇博客

##cpu 密集型機器

cpu 密集型服務器的vmstat 輸出通常在us 列會有一個很高的值,報告了花費在非內核代碼上的cpu 時鍾;也可能在sy 列有很高的值,表示系統cpu 利用率,超過20% 就足以令人不安了。在大部分情況下,也會有進程隊列排隊時間(在r列報告的)。下面是一個列子:

如果我們在同一台及其上觀察iostat 的輸出(再次剔除顯示啟動以來平均值的第一行),可以發現磁盤利用率低於50%:

這台機器不是IO密集型的,但是依然有相當數量的IO發生,在數據庫服務器中這種情況很少見。另一方面,傳統的Web 服務器會消耗掉大量的CPU 資源,但是很少發生IO,所以Web 服務器的輸出不會像這個例子。

##IO 密集型機器

在IO密集型工作負載下,CPU花費大量時間在等待IO請求完成。這意味着vmstat 會顯示很多處理器在非中斷休眠(b列)狀態,並且在wa 這一列的值很高,下面是個例子:

這台機器的iostat 輸出顯示硬盤一直很忙:

%util的值可能因為四舍五入的錯誤超過100%。什么跡象意味着機器是IO密集的呢?只要有足夠的緩沖來服務寫請求,即使機器正在做大量的寫操作,也可能可以滿足,但是卻通常意味着硬盤可能會無法滿足讀請求。這聽起來好像違反直覺,但是如果思考讀和寫的本質,就不會這么認為了:

  • 寫請求能夠緩沖或同步操作。
  • 讀請求就其本質而言都是同步的。當然,程序可以猜測到可能需要某些數據,並異步地提前讀取(預讀)。無論如何,通常程序在繼續工作前必須得到它們需要的數據。這就強制讀請求為同步操作:程序必須阻塞直到請求完成。

想想這種方式:你可以發出一個寫請求到緩沖區的某個地方,然后過一會完成。甚至可以每秒發出很多這樣的請求。如果緩沖區正確工作,並且有足夠的空間,每個請求都可以很快完成,並且實際上寫到物理硬盤是被重新排序后更有效地批量操作的。然而,沒有辦法對讀操作這么做————不管多小或多少的請求,都不可能讓硬盤響應說:”這是你的數據,我等一會讀它”。這就是為什么讀需要IO等待是可以理解的原因。

##發生內存交換的機器

一台正在發生內存交換的機器可能在swpd 列有一個很高的值,也可能不高。但是可以看到si 和 so 列有很高的值,這是我們不希望看到的。下面是一台內存交換嚴重的機器的vmstat 輸出:

##空閑的機器

下面是一台空閑機器上的vmstat輸出。可以看到idle列顯示CPU是100%的空閑。

#dstat

dstat 顯示了cpu使用情況,磁盤io 情況,網絡發包情況和換頁情況。

個人覺得,iostat和vmstat 的輸出雖然詳細,但是不夠直觀,不如dstat 好用。而且,dstat輸出是彩色的,可讀性更強。現在dstat作為我首選的,查看系統狀態的工具。

dstat使用時,直接輸入命令即可,不用任何參數。也可以通過指定參數來顯示更加詳細的信息。

dstat -cdlmnpsy

dstat

#iotop

通過iostat和dstat我們可以知道系統的當前IO負載,但是IO負載具體是由哪個進程產生的呢?這時候我們需要的是iotop.

iotop是一個用來監視磁盤I/O使用狀況的top類工具,具有與top相似的UI,其中包括PID、用戶、I/O、進程等相關信息。 iotop使用Python語言編寫而成,要求Python 2.5(及以上版本)和Linux kernel 2.6.20(及以上版本)。使用非常簡單,在此不做過多介紹,詳細信息參見官網:http://guichaz.free.fr/iotop/

這個命令也可以以非交互的方式使用:

iotop -bod interval

查看每個進程的IO,也可以通過pidstat命令,不像iotop,且pidstat還不需要root權限。

pidstat -d interval

#pidstat

了解系統IO的情況大多數是通過iostat來獲取的,這個粒度只能精確到每個設備。通常我們會想了 解每個進程,線程層面發起了多少IO,在Linux 2.6.20之前除了用systemtap這樣的工具來實現 是沒有其他方法的,因為系統沒有暴露這方面的統計。現在可以通過一個名為pidstat的工具, 它的使用方法如下:

pidstat -d interval

此外,pidstat 還可以用以統計CPU使用信息。

pidstat -u interval

統計內存信息:

pidstat -r interval

#top

top 命令的匯總區域顯示了五個方面的系統性能信息: 1. 負載:時間,登錄用戶數,系統平均負載 2. 進程:運行,睡眠,停止,僵屍 3. CPU :用戶態,核心態,NICE,空閑,等待IO,中斷等 4. 內存:總量,已用,空閑(系統角度),緩沖,緩存 5. 交換分區:總量,已用,空閑

任務區域默認顯示:進程ID,有效用戶,進程優先級,NICE值,進程使用的虛擬內存,物理內存和共享內存,進程狀態,CPU 占用率,內存占用率,累計CPU時間,進程命令行信息。

#htop 另一個更好用的top的替代工具是htop,htop是Linux系統中的一個互動的進程查看器,一個文本模式的應用程序(在控制台或者X終端中),需要ncurses。

htop

與Linux傳統的top相比,htop更加人性化。它可讓用戶交互式操作,支持顏色主題,可橫向或縱向滾動瀏覽進程列表,並支持鼠標操作。

與top相比,htop有以下優點:

  • 可以橫向或縱向滾動瀏覽進程列表,以便看到所有的進程和完整的命令行。
  • 在啟動上,比top 更快。
  • 殺進程時不需要輸入進程號。
  • htop 支持鼠標操作。

參考資料:Linux下取代top的進程管理工具 htop

#mpstat

mpstat 用來統計多核處理器中,每一個處理器的使用情況。mpstat使用方法很簡單,常見用法如下:

mpstat -P ALL interval times

不出意外,讀者執行上面的命令,看不出個所以然來,試試在運行下面這條命令的同時,查看mpstat的輸出。

sysbench --test=cpu --cpu-max-prime=20000 run

注意:sysbench是一個基准測試工具,可以用來測試cpu,io,mutex,oltp等。在Debain系統下, 通過下面的命令安裝:

sudo apt-get install sysbench 

#netstat

netstat用於顯示與IP、TCP、UDP和ICMP協議相關的統計數據,一般用於檢驗本機各端口的網絡連接情況。

就我自己而言,經常使用的用法如下:

netstat -npl

上面這條命令可以查看你要打開的端口是否已經打開,以此來作為程序是否已經啟動的依據。

netstat 還有很多其他的用法,在《TCP/IP詳解》一書中,作者喜歡用netstat命令來打印路由表,使用方法如下:

netstat -rn

其中,flag域的解釋如下:

  • U 該路由可用
  • G 該路由是到一個到網關(路由器)。如果沒有設置該標志,說明目的地址是直接相連的
  • H 該路由是到一個主機
  • D 該路由是由重定向報文創建
  • M 該路由已被重定向報文修改

netstat 也可以提供系統上的接口信息:

netstat -in

這個命令打印每個接口的MTU,輸入分組數,輸入錯誤,輸出分組數,輸出錯誤,沖突以及當前的輸出隊列的長度。

#ps

最最常用的用法

ps aux #BSD ps -ef #linux

ps 參數太多,具體使用方法,請man ps,下面是兩種相對常用的使用方式。

  • 殺掉某一程序的方法。

     ps aux | grep mysqld | grep -v grep | awk '{ print $2 }' | xargs kill -9
  • 殺掉僵屍進程:

     ps -eal | awk '{ if ($2 == "Z" ){ print $4}}' | xargs kill -9

#strace

用我自己的理解來介紹strace:

我們寫程序,會調用很多庫函數,而這些庫函數,只是對系統調用的封裝,它們最后都會去調用操作系統提供的系統調用,通過系統調用去訪問硬件設備。strace的作用就是顯示出這些調用關系,讓程序員知道調用一個函數,它到底做了些什么事情。當然,strace 遠比上面的介紹靈活多變。

下面來看一個例子:

查看mysqld 在linux上加載哪種配置文件,可以通過運行下面的命令行:

strace -e stat64 mysqld --print-defaults > /dev/null

strace太強大,內容也太多了,我找到一篇比較好的,介紹strace的文章,請點擊這里

#uptime

uptime是最最最最簡單的工具了,但是也有值得討論的地方,那就是它最后輸出的三個數字是怎么得來的,有什么含義?

這三個數字的含義分別是1分鍾、5分鍾、15分鍾內系統的平均負荷,關於這些數字的含義和由來,推薦看阮一峰的文章《理解linux系統負荷這里》。

我想說的是,這三個數字我天天看,時時看,但是我從來不相信它。

此話怎講呢?我之所以天天看,時時看,是因為我將這三個數字顯示到了tmux 的狀態欄上,所以,我任何時候都可以看到,而不用專門輸入uptime這個命令。

為什么我不相信它呢,因為這幾個數字只能說明有多少線程在等待cpu,如果我們的一個任務有很多線程,系統負載不是特別高,但是這幾個數字會出奇的高,也就是不能完全相信uptime的原因。如果不信,可以執行下面這條語句,然后再看看uptime的輸出結果。

sysbench --test=mutex --num-threads=1600 --mutex-num=2048 \ --mutex-locks=1000000 --mutex-loops=5000 run

運行了5分鍾以后,我的電腦上輸出如下所示。需要強調的是,這個時候電腦一點不卡,看uptime來判斷系統負載,跟聽cpu風扇聲音判斷系統負載一樣。只能作為線索,不能作為系統負載很高的依據。

 20:32:39 up 10:21, 4 users, load average: 386.53, 965.37, 418.57

《Linux Performance Analysis and Tools》里面也說了,This is only useful as a clue. Use other tools to investigate!

#lsof

lsof(list open files)是一個列出當前系統打開文件的工具。在linux環境下,任何事物都以 文件的形式存在,通過文件不僅僅可以訪問常規數據,還可以訪問網絡連接和硬件。所以如傳輸 控制協議(TCP)和用戶數據報協議(UDP)套接字等,系統在后台都為該應用程序分配了一個文件描 述符,無論這個文件的本質如何,該文件描述符為應用程序與基礎操作系統之間的交互提供了 通用接口。因為應用程序打開文件的描述符列表提供了大量關於這個應用程序本身的信息,因此 通過lsof工具能夠查看這個列表對系統監測以及排錯將是很有幫助的。

lsof 的使用方法可以參考這里。這里僅列出幾種常見的用法。

  1. 查看文件系統阻塞 lsof /boot

  2. 查看端口號被哪個進程占用 lsof -i :3306

  3. 查看用戶打開哪些文件 lsof -u username

  4. 查看進程打開哪些文件 lsof -p 4838

  5. 查看遠程已打開的網絡鏈接 lsof -i @192.168.34.128

參考資料:

  1. Linux常用監控命令介紹
  2. 使用lsof查找打開的文件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM