Linux 效能查看命令:
Linux效能監測:CPU篇
CPU 的佔用主要取決於什麼樣的資源正在 CPU 上面運行,比如拷貝一個檔案通常佔用較少 CPU,因為大部分工作是由 DMA(Direct Memory Access)完成,只是在完成拷貝以後給一個中斷讓 CPU 知道拷貝已經完成;科學計算通常佔用較多的 CPU,大部分計算工作都需要在 CPU 上完成,記憶體、硬碟等子系統只做暫時的資料存放區工作。要想監測和理解 CPU 的效能需要知道一些的作業系統的基本知識,比如:中斷、進程調度、進程環境切換、可運行隊列等。這裡 VPSee 用個例子來簡單介紹一下這些概念和他們的關係,CPU 很無辜,是個任勞任怨的打工仔,每時每刻都有工作在做(進程、線程)並且自己有一張工作清單(可運行隊列),由老闆(進程調度)來決定他該幹什麼,他需要 和老闆溝通以便得到老闆的想法並及時調整自己的工作(環境切換),部分工作做完以後還需要及時向老闆彙報(中斷),所以打工仔(CPU)除了做自己該做 的工作以外,還有大量時間和精力花在溝通和彙報上。
CPU 也是一種硬體資源,和任何其他硬體裝置一樣也需要驅動和管理程式才能使用,我們可以把核心的進程調度看作是 CPU 的管理程式,用來管理和分配 CPU 資源,合理安排進程搶佔 CPU,並決定哪個進程該使用 CPU、哪個進程該等待。作業系統核心裡的進程調度主要用來調度兩類資源:進程(或線程)和中斷,進程調度給不同的資源分派了不同的優先順序,優先順序最高的 是硬體中斷,其次是核心(系統)進程,最後是使用者進程。每個 CPU 都維護著一個可運行隊列,用來存放那些可啟動並執行線程。線程要麼在睡眠狀態(blocked 正在等待 IO)要麼在可運行狀態,如果 CPU 當前負載太高而新的請求不斷,就會出現進程調度暫時應付不過來的情況,這個時候就不得不把線程暫時放到可運行隊列裡。VPSee 在這裡要討論的是效能監測,上面談了一堆都沒提到效能,那麼這些概念和效能監測有什麼關係呢。關係重大。如果你是老闆,你如何檢查打工仔的效率(效能) 呢。我們一般會通過以下這些資訊來判斷打工仔是否偷懶:
· 打工仔接受和完成多少任務並向老闆彙報了(中斷);
· 打工仔和老闆溝通、協商每項工作的工作進度(環境切換);
· 打工仔的工作列表是不是都有排滿(可運行隊列);
· 打工仔工作效率如何,是不是在偷懶(CPU 利用率)。
現在把打工仔換成 CPU,我們可以通過查看這些重要參數:中斷、環境切換、可運行隊列、CPU 利用率來監測 CPU 的效能。
底線
Linux 效能監測:介紹提到了效能監測前需要知道底線,那麼監測 CPU 效能的底線是什麼呢。通常我們期望我們的系統能到達以下目標:
· CPU 利用率,如果 CPU 有 100% 利用率,那麼應該到達這樣一個平衡:65%-70% User Time,30%-35% System Time,0%-5% Idle Time;
· 環境切換,環境切換應該和 CPU 利用率聯絡起來看,如果能保持上面的 CPU 利用率平衡,大量的環境切換是可以接受的;
· 可運行隊列,每個可運行隊列不應該有超過1-3個線程(每處理器),比如:雙處理器系統的可運行隊列裡不應該超過6個線程。
cpu監控分為兩種:cpu使用率和IPC/CPI,兩者的應用情境也不相同,
通常使用的是cpu使用率監控,基本上作業系統都會提供,
IPC/CPI監控則需要效能專家的協助,作業系統上基本沒有相關的指令
cpu的使用率需要關注使用者態cpu使用率和系統態cpu使用率,前者表示系統上運行業務獲得cpu的執行時間佔總cpu時間的百分比,後者表示系統獲得cpu時間的百分比。對使用者而言,使用者態cpu百分比為100%是最理想的狀況,但這通常不可能,當出現程式調度、線程環境切換以及IO互動的時候,系統態cpu使用率會較多的增長。應當明確的是,應用消耗很多CPU並不意味著效能或者擴充性達到了最高或瓶頸。如果長時間出現系統態cpu使用率居高不下,那麼就需要關注,有可能是程式寫的不優雅,有可能是磁碟即將損壞導致IO消耗時間過長,這時候就需要cpu監控從而分析得出結果
對計算密集型應用來首,只監控cpu使用率是不夠的,還需要監控IPC(每時鐘指令數)或CPI(每指令刻度)。為什麼需要知道這一項資料。IPC或CPI都可以反映了沒有指令被執行的時候佔用cpu刻度的百分比,簡而言之就是CPU等待指令從記憶體中裝入寄存器消耗時間的百分比,即停滯(stall)。停滯——當cpu執行指令而所用到的運算元不在寄存器或緩衝中並且當前鐘周期還未失效時,cpu就需要停滯等待資料從記憶體中裝入寄存器,停滯一旦發生,通常會浪費幾百個cpu刻度。要想提高計算密集型應用的效能,就需要獲得IPC/CPI監控資料,減少停滯減少cpu等待記憶體資料時間或改善快取。
Linux效能監測:記憶體篇
這裡的講到的 “記憶體” 包括實體記憶體和虛擬記憶體,虛擬記憶體(Virtual Memory)把電腦的記憶體空間擴充到硬碟,實體記憶體(RAM)和硬碟的一部分空間(SWAP)組合在一起作為虛擬記憶體為電腦提供了一個連貫的虛擬內 存空間,好處是我們擁有的記憶體 ”變多了“,可以運行更多、更大的程式,壞處是把部分硬碟當記憶體用整體效能受到影響,硬碟讀寫速度要比記憶體慢幾個數量級,並且 RAM 和 SWAP 之間的交換增加了系統的負擔。
在作業系統裡,虛擬記憶體被分成頁,在 x86 系統上每個頁大小是 4KB。Linux 核心讀寫虛擬記憶體是以 “頁” 為單位操作的,把記憶體轉移到硬碟交換空間(SWAP)和從交換空間讀取到記憶體的時候都是按頁來讀寫的。記憶體和 SWAP 的這種交換過程稱為頁面交換(Paging),值得注意的是 paging 和 swapping 是兩個完全不同的概念,國內很多參考書把這兩個概念混為一談,swapping 也翻譯成交換,在作業系統裡是指把某程式完全交換到硬碟以騰出記憶體給新程式使用,和 paging 只交換程式的部分(頁面)是兩個不同的概念。純粹的 swapping 在現代作業系統中已經很難看到了,因為把整個程式交換到硬碟的辦法既耗時又費力而且沒必要,現代作業系統基本都是 paging 或者 paging/swapping 混合,swapping 最初是在 Unix system V 上實現的。
虛擬記憶體管理是 Linux 核心裡面最複雜的部分,要弄懂這部分內容可能需要一整本書的講解。VPSee 在這裡只介紹和效能監測有關的兩個核心進程:kswapd 和 pdflush。
• kswapd daemon 用來檢查 pages_high 和 pages_low,如果可用記憶體少於 pages_low,kswapd 就開始掃描並試圖釋放 32個頁面,並且重複掃描釋放的過程直到可用記憶體大於 pages_high 為止。掃描的時候檢查3件事:1)如果頁面沒有修改,把頁放到可用記憶體列表裡;2)如果頁面被檔案系統修改,把頁面內容寫到磁碟上;3)如果頁面被修改 了,但不是被檔案系統修改的,把頁面寫到交換空間。
• pdflush daemon 用來同步檔案相關的記憶體頁面,把記憶體頁面及時同步到硬碟上。比如開啟一個檔案,檔案被匯入到記憶體裡,對檔案做了修改後並儲存後,核心並不馬上儲存檔案到硬 盤,由 pdflush 決定什麼時候把相應頁面寫入硬碟,這由一個核心參數 vm.dirty_background_ratio 來控制,比如下面的參數顯示髒頁面(dirty pages)達到所有記憶體頁面10%的時候開始寫入硬碟。
Linux效能監測:磁碟IO篇
磁碟通常是電腦最慢的子系統,也是最容易出現效能瓶頸的地方,因為磁碟離 CPU 距離最遠而且 CPU 訪問磁碟要涉及到機械操作,比如轉軸、尋軌等。訪問硬碟和訪問記憶體之間的速度差別是以數量級來計算的,就像1天和1分鐘的差別一樣。要監測 IO 效能,有必要瞭解一下基本原理和 Linux 是如何處理硬碟和記憶體之間的 IO 的。 記憶體頁 上一篇 Linux 效能監測:Memory 提到了記憶體和硬碟之間的 IO 是以頁為單位來進行的,在 Linux 系統上1頁的大小為 4K。可以用以下命令查看系統預設的頁面大小:
?
1 2 3 4 |
$ /usr/bin/time -vdate ... Page size (bytes): 4096 ... |
缺頁中斷 Linux 利用虛擬記憶體極大的擴充了程式地址空間,使得原來實體記憶體不能容下的程式也可以通過記憶體和硬碟之間的不斷交換(把暫時不用的記憶體頁交換到硬碟,把需要的內 存頁從硬碟讀到記憶體)來贏得更多的記憶體,看起來就像實體記憶體被擴大了一樣。事實上這個過程對程式是完全透明的,程式完全不用理會自己哪一部分、什麼時候被 交換進記憶體,一切都有核心的虛擬記憶體管理來完成。當程式啟動的時候,Linux 核心首先檢查 CPU 的緩衝和實體記憶體,如果資料已經在記憶體裡就忽略,如果資料不在記憶體裡就引起一個缺頁中斷(Page Fault),然後從硬碟讀取缺頁,並把缺頁緩衝到實體記憶體裡。缺頁中斷可分為主缺頁中斷(Major Page Fault)和次缺頁中斷(Minor Page Fault),要從磁碟讀取資料而產生的中斷是主缺頁中斷;資料已經被讀入記憶體並被緩衝起來,從記憶體緩衝區中而不是直接從硬碟中讀取資料而產生的中斷是次 缺頁中斷。 上面的記憶體緩衝區起到了預讀硬碟的作用,核心先在實體記憶體裡尋找缺頁,沒有的話產生次缺頁中斷從記憶體緩衝裡找,如果還沒有發現的話就從硬碟讀取。很 顯然,把多餘的記憶體拿出來做成記憶體緩衝區提高了訪問速度,這裡還有一個命中率的問題,運氣好的話如果每次缺頁都能從記憶體緩衝區讀取的話將會極大提高效能。 要提高命中率的一個簡單方法就是增大記憶體緩衝區面積,緩衝區越大預存的頁面就越多,命中率也會越高。下面的 time 命令可以用來查看某程式第一次啟動的時候產生了多少主缺頁中斷和次缺頁中斷:
$ /usr/bin/time -vdate
...
Major (requiring I/O) page faults: 1
Minor (reclaiming a frame) page faults: 260
...
File Buffer Cache
從上面的記憶體緩衝區(也叫檔案快取區 File Buffer Cache)讀取頁比從硬碟讀取頁要快得多,所以 Linux 核心希望能儘可能產生次缺頁中斷(從檔案快取區讀),並且能儘可能避免主缺頁中斷(從硬碟讀),這樣隨著次缺頁中斷的增多,檔案快取區也逐步增大,直到系 統只有少量可用實體記憶體的時候 Linux 才開始釋放一些不用的頁。我們運行 Linux 一段時間後會發現雖然系統上啟動並執行程式不多,但是可用記憶體總是很少,這樣給大家造成了 Linux 對記憶體管理很低效的假象,事實上 Linux 把那些暫時不用的實體記憶體高效的利用起來做預存(記憶體緩衝區)呢。下面列印的是 VPSee 的一台 Sun 伺服器上的實體記憶體和檔案快取區的情況:
?
1 2 3 4 5 |
$ cat /proc/meminfo MemTotal: 8182776 kB MemFree: 3053808 kB Buffers: 342704 kB Cached: 3972748 kB |
這台伺服器總共有 8GB 實體記憶體(MemTotal),3GB 左右可用記憶體(MemFree),343MB 左右用來做磁碟緩衝(Buffers),4GB 左右用來做檔案快取區(Cached),可見 Linux 真的用了很多實體記憶體做 Cache,而且這個緩衝區還可以不斷增長。
頁面類型
Linux 中記憶體頁面有三種類型:
· Read pages,唯讀頁(或字碼頁),那些通過主缺頁中斷從硬碟讀取的頁面,包括不能修改的靜態檔案、可執行檔、庫檔案等。當核心需要它們的時候把它們讀到 記憶體中,當記憶體不足的時候,核心就釋放它們到空閑列表,當程式再次需要它們的時候需要通過缺頁中斷再次讀到記憶體。
· Dirty pages,髒頁,指那些在記憶體中被修改過的資料頁,比如文字檔等。這些檔案由 pdflush 負責同步到硬碟,記憶體不足的時候由 kswapd 和 pdflush 把資料寫回硬碟並釋放記憶體。
· Anonymous pages,匿名頁,那些屬於某個進程但是又和任何檔案無關聯,不能被同步到硬碟上,記憶體不足的時候由 kswapd 負責將它們寫到交換分區並釋放記憶體。
IO’s Per Second(IOPS)
每次磁碟 IO 請求都需要一定的時間,和訪問記憶體比起來這個等待時間簡直難以忍受。在一台 2001 年的典型 1GHz PC 上,磁碟隨機訪問一個 word 需要 8,000,000 nanosec = 8 millisec,順序訪問一個 word 需要 200 nanosec;而從記憶體訪問一個 word 只需要 10 nanosec.(資料來自:Teach Yourself Programming in Ten Years)這個硬碟可以提供 125 次 IOPS(1000 ms / 8 ms)。
順序 IO 和 隨機 IO
IO 可分為順序 IO 和 隨機 IO 兩種,效能監測前需要弄清楚系統偏向順序 IO 的應用還是隨機 IO 應用。順序 IO 是指同時順序請求大量資料,比如資料庫執行大量的查詢、流媒體服務等,順序 IO 可以同時很快的移動大量資料。可以這樣來評估 IOPS 的效能,用每秒讀寫 IO 位元組數除以每秒讀寫 IOPS 數,rkB/s 除以 r/s,wkB/s 除以 w/s. 下面顯示的是連續2秒的 IO 情況,可見每次 IO 寫的資料是增加的(45060.00 / 99.00 = 455.15 KB per IO,54272.00 / 112.00 = 484.57 KB per IO)。相對隨機 IO 而言,順序 IO 更應該重視每次 IO 的吞吐能力(KB per IO):
?
1 2 3 4 5 6 7 8 9 10 11 12 |
$ iostat -kx 1 avg-cpu: %user %nice %system %iowait %steal %idle 0.00 0.00 2.50 25.25 0.00 72.25 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util sdb 24.00 19995.00 29.00 99.00 4228.00 45060.00 770.12 45.01 539.65 7.80 99.80 avg-cpu: %user %nice %system %iowait %steal %idle 0.00 0.00 1.00 30.67 0.00 68.33 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util sdb 3.00 12235.00 3.00 112.00 768.00 54272.00 957.22 144.85 576.44 8.70 100.10 |
隨機 IO 是指隨機請求資料,其 IO 速度不依賴於資料的大小和排列,依賴於磁碟的每秒能 IO 的次數,比如 Web 服務、Mail 服務等每次請求的資料都很小,隨機 IO 每秒同時會有更多的請求數產生,所以磁碟的每秒能 IO 多少次是關鍵。
?
1 2 3 4 5 6 7 8 9 10 11 12 |
$ iostat -kx 1 avg-cpu: %user %nice %system %iowait %steal %idle 1.75 0.00 0.75 0.25 0.00 97.26 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util sdb 0.00 52.00 0.00 57.00 0.00 436.00 15.30 0.03 0.54 0.23 1.30 avg-cpu: %user %nice %system %iowait %steal %idle 1.75 0.00 0.75 0.25 0.00 97.24 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util sdb 0.00 56.44 0.00 66.34 0.00 491.09 14.81 0.04 0.54 0.19 1.29 |
按照上面的公式得出:436.00 / 57.00 = 7.65 KB per IO,491.09 / 66.34 = 7.40 KB per IO. 與順序 IO 比較發現,隨機 IO 的 KB per IO 小到可以忽略不計,可見對於隨機 IO 而言重要的是每秒能 IOPS 的次數,而不是每次 IO 的吞吐能力(KB per IO)。
SWAP
當系統沒有足夠實體記憶體來應付所有請求的時候就會用到 swap 裝置,swap 裝置可以是一個檔案,也可以是一個磁碟分割。不過要小心的是,使用 swap 的代價非常大。如果系統沒有實體記憶體可用,就會頻繁 swapping,如果 swap 裝置和程式正要訪問的資料在同一個檔案系統上,那會碰到嚴重的 IO 問題,最終導致整個系統遲緩,甚至崩潰。swap 裝置和記憶體之間的 swapping 狀況是判斷 Linux 系統效能的重要參考,我們已經有很多工具可以用來監測 swap 和 swapping 情況,比如:top、cat /proc/meminfo、vmstat 等:
?
1 2 3 4 5 6 7 8 9 10 |
$ cat /proc/meminfo MemTotal: 8182776 kB MemFree: 2125476 kB Buffers: 347952 kB Cached: 4892024 kB SwapCached: 112 kB ... SwapTotal: 4096564 kB SwapFree: 4096424 kB ... |
Linux效能監測:網路篇
網路的監測是所有 Linux 子系統裡面最複雜的,有太多的因素在裡面,比如:延遲、阻塞、衝突、丟包等,更糟的是與 Linux 主機相連的路由器、交換器、無線訊號都會影響到整體網路並且很難判斷是因為 Linux 網路子系統的問題還是別的裝置的問題,增加了監測和判斷的複雜度。現在我們使用的所有網卡都稱為自適應網卡,意思是說能根據網路上的不同網路裝置導致的不 同網路速度和工作模式進行自動調整。我們可以通過 ethtool 工具來查看網卡的配置和工作模式:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# /sbin/ethtool eth0 Settings for eth0: Supported ports: [ TP ] Supported link modes: 10baseT/Half10baseT/Full 100baseT/Half100baseT/Full 1000baseT/Half1000baseT/Full Supports auto-negotiation: Yes Advertised link modes: 10baseT/Half10baseT/Full 100baseT/Half100baseT/Full 1000baseT/Half1000baseT/Full Advertised auto-negotiation: Yes Speed: 100Mb/s Duplex: Full Port: Twisted Pair PHYAD: 1 Transceiver: internal Auto-negotiation: on Supports Wake-on: g Wake-on: g Current message level: 0x000000ff (255) Link detected: yes |
上面給出的例子說明網卡有 10baseT,100baseT 和 1000baseT 三種選擇,目前正自適應為 100baseT(Speed: 100Mb/s)。可以通過 ethtool 工具強制網卡工作在 1000baseT 下:
/sbin/ethtool -s eth0 speed 1000 duplex full autoneg off
Linux效能監測:常用命令
1 :uptime 查看當前系統的負載狀況
09:50:21 up 200 days, 15:07, 1 user, load average: 0.27, 0.33, 0.3
2:dmesg |tail 查看開機列印資訊和環形緩衝區的內容。
3 :vmstat 監控系統(記憶體,cpu,磁碟,io,網卡)狀態
vmstat 1 表示每秒鐘採集一次。
vmstat 1 10 表示每秒鐘採集一次,共十次。
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 0 3932924 230676 1280388 0 0 0 5 4 16 5 6 89 0 0
0 0 0 3932916 230676 1280388 0 0 0 0 1147 1314 7 9 84 0 0
0 0 0 3932908 230676 1280388 0 0 0 16 439 1245 0 0 99 0 0
0 0 0 3932908 230676 1280388 0 0 0 0 699 1381 1 0 99 0 0
1 0 0 3932908 230676 1280388 0 0 0 0 1106 1328 6 8 86 0 0
0 0 0 3932908 230676 1280388 0 0 0 0 660 1332 2 2 96 0 0
1 0 0 3932908 230676 1280388 0 0 0 20 1122 1250 7 8 85 0 0
2 0 0 3932916 230676 1280388 0 0 0 4 2001 1463 14 19 67 0 0
0 0 0 3932792 230676 1280388 0 0 0 0 1111 1375 5 4 90 0 0
0 0 0 3932792 230676 1280388 0 0 0 0 589 1295 1 0 99 0 0
procs(進程):
r 表示等待可用cpu 資源的進程數量(如果長時間該值超過處理器硬體執行緒個數一倍,需要關注了。)。
硬體執行緒個數 :dmesg |grep CPU可以查看。
b 表示阻塞的進程個數(阻塞是說需要其他資源,比如io)
swap(交換分區):兩個值都大就表示系統記憶體資源緊張。
si: 每秒鐘從磁碟寫入swap的大小,
so: 每秒從記憶體寫入swap的大小
memory
swpd:
swap已使用的大小,如果大於0,表示你的機器實體記憶體不足了,如果不是程式記憶體泄露的原因,那麼你該升級記憶體了或者把耗記憶體的任務遷移到其他機器,如果swpd不為0,但是si,so的值長期為0,不影響系統效能
free :閒置實體記憶體多大小。
buff:用來儲存,目錄裡面有什麼內容,許可權等的緩衝
cache:直接用來記憶我們開啟的檔案,給檔案做緩衝
io:
bi:從磁碟或者swap讀取到ram,每秒讀取的塊數。
bo: 從ram寫入到磁碟或者swap,每秒寫入的塊數。
注意:隨機磁碟讀寫的時候,這2個值越大(如超出1024k),能看到CPU在IO等待的值也會越大
系統:
in:每秒中斷數,包括時鐘中斷。
cs:每秒環境切換數。
例如我們調用系統函數,就要進行環境切換,線程的切換,也要進程環境切換,這個值要越小越好,太大了,要考慮調低線程或者進程的數目,例如在apache和nginx這種web伺服器中,我們一般做效能測試時會進行幾千並發甚至幾萬並發的測試,選擇web伺服器的進程可以由進程或者線程的峰值一直下調,壓測,直到cs到一個比較小的值,這個進程和線程數就是比較合適的值了。系統調用也是,每次調用系統函數,我們的代碼就會進入核心空間,導致環境切換,這個是很耗資源,也要盡量避免頻繁調用系統函數。環境切換次數過多表示你的CPU大部分浪費在環境切換,導致CPU幹正經事的時間少了,CPU沒有充分利用,是不可取的。
cpu:
us:使用者CPU時間,但是如果長期超50%的使用,那麼我們就該考慮最佳化程式演算法或者進行加速。