前言html
何爲性能優化?我的認爲,性能優化是爲了提升應用程序或系統能力爲目的。那麼如何才能實現對應用程序的性能調優呢?這裏很設計到不少的內容,包括Linux內核、CPU架構以及Linux內核對資源的分配以及管理,瞭解進程的建立過程等。這方面因爲篇幅較多,因此個人文章就不過多介紹。接下來的幾篇文章中,都是講解如何發現應用程序故障根源爲目標講解,這也是每個系統工程師應該具有的能力。廢話很少說,我直接進入主題。nginx
經常使用術語web
延時:延時是描述操做以後用來等待返回結果的時間。在某些狀況下,它能夠指的是整個操做時間,等同於響應時間。redis
IOPS:每秒發生的輸入/輸出操做的次數,是數據傳輸的一個度量方法。對於磁盤的讀寫,IOPS指的是每秒讀寫的次數。算法
響應時間:通常操做完成的時間。包括用於等待和服務的時間,也包括用來返回結果的時間。apache
使用率:對於服務所請求的資源,使用率描述在所給定時間區間內資源的繁忙程度。對於春初資源來講,使用率指的就是所消耗的存儲容量。數組
飽和度:指的就是某一資源沒法知足服務的排隊工做量。緩存
吞吐量:評價工做秩序的速率,尤爲是在數據傳輸方面,這個屬於用於數據傳輸速度(字節/秒和比特/秒)。在某些狀況下,吞吐量指的是操做的速度。性能優化
Linux內核功能bash
CPU調度級別:各類先進的CPU調度算法,非一直存儲訪問架構(NUMA);
I/O調度界別:I/O調度算法,包括deadline/anticipatory和徹底公平隊列(CFQ);
TCP網絡阻塞:TCP擁堵算法,容許按需選擇;
常見問題
進程、線程和任務之間的區別是什麼?
進程一般定義爲程序的執行。用以執行用戶級別程序的環境。它包括內存地址空間、文件描述符、線程棧和寄存器。
線程是某一進程中單獨運行的程序。也就是說線程在進程之中。
任務是程序完成的某一活動,可使一個進程,也能夠是一個線程。
參考鏈接:http://blog.chinaunix.net/uid-25100840-id-271078.html
什麼是上下文切換?
執行一段程序代碼,實現一個功能的過程介紹,當獲得CPU的時候,相關的資源必須也已經就位,就是顯卡、內存、GPS等,而後CPU開始執行。這裏除了CPU之外全部的就構成了這個程序的執行環境,也就是咱們所定義的程序上下文。當這個程序執行完或者分配給他的CPU執行時間用完了,那它就要被切換出去,等待下一次CPU的臨幸。在被切換出去的最後一步工做就是保存程序上下文,由於這個是下次他被CPU臨幸的運行環境,必須保存。
I/O密集型和CPU密集型工做負載之間的區別?
I/O密集型指的是系統的CPU耗能相對硬盤/內存的耗能能要好不少,此時,系統運做,大部分的情況是 CPU 在等 I/O(硬盤/內存)的讀/寫,此時CPU負載不高。CPU密集型指的是系統的硬盤/內存耗能相對CPU的耗能要好不少,此時,系統運做,大部分的情況是 CPU負載 100%,CPU 要讀/寫 I/O (硬盤/內存),I/O在很短的時間就能夠完成,而CPU還有許多運算要處理,CPU負載很高。通常而言CPU佔用率至關高,大部份時間用來作計算、邏輯判斷等CPU動做的程序。
應用程序性能技術
1.選擇I/O尺寸
執行I/O的開銷包括初始化緩衝區、系統調用、上下文切換、分配內核元數據、檢查進程權限和限制、映射地址到設備、執行內核和驅動代碼來執行I/O,以及在最後釋放元數據和緩衝區。增長I/O尺寸是應用程序提升吞吐量的經常使用策略。
2.緩存
操做系統用緩存提升文件系統的讀性能和內存的分配性能,應用程序使用緩存也處於相似的緣由。將常常執行的操做結果保存在本地緩存中以備後用,而非老是執行開銷較高的操做。
3.緩衝區
爲了提升寫操做性能,數據在送入下一層級以前會合並並放在緩衝區中。這樣會增長寫延時,由於第一次寫入緩衝區後,在發送以前,還要等待後續的寫入。
4. 併發和並行
並行:裝在和開始執行多個可運行程序的能力(好比,同時接電話和吃飯)。爲了利用多核處理器系統的優點,應用程序須要在同一時間運行在多顆CPU上,這種方式稱爲並行。應用程序經過多進程或多線程實現。
併發:有處理多個任務的能力,不必定要同時。好比,接完電話在去吃飯,存在資源搶佔;
同步原語:同步原語監管內存的訪問,當不容許訪問時,就會引發等待時間(延時)。常見三種類型:
mutex鎖:只有鎖持有者才能操做,其餘線程會阻塞並等待CPU;
自旋鎖:自旋鎖容許鎖持有者操做,其餘的須要自旋鎖的線程會在CPU上循環自選,檢查鎖是否被釋放。雖然這樣能夠提供低延時的訪問,被阻塞的線程不會離開CPU,時刻準備着運行知道鎖可用,可是線程自旋、等待也是對CPU資源的浪費。
讀寫鎖:讀/寫鎖經過容許多個讀者或者只容許一個寫者而沒有讀者,來保證數據的完整性。
自適應自旋鎖:低延遲的訪問而不浪費CPU資源,是mutex鎖和自旋鎖的混合。
5.綁定CPU
關於CPU性能分析
uptime:
系統負載,經過彙總正在運行的線程數和正在排隊等待運行的線程數計算得出。分別反映1/5/15分鐘之內的負載。如今的平均負載不只用來表示CPU餘量或者飽和度,也不能單從這個值推斷出CPU或者磁盤負載。
vmstat:
虛擬內存統計信息命令。最後幾列打印系統全局範圍內的CPU使用狀態,在第一列顯示可運行進程數。以下所示:
[root@zbredis-30104 ~]# vmstat 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 0 14834208 158384 936512 0 0 0 0 1 3 0 0 100 0 0
提示:
r: 運行隊列長度和正在運行的線程數;
b: 表示阻塞的進程數;
swpd: 虛擬內存已使用的大小,若是大於0,表示你的機器物理內存不足了,若是不是程序內存泄露的緣由,那麼你該升級內存了或者把耗內存的任務遷移到其餘機器;
si: 每秒從磁盤讀入虛擬內存的大小,若是這個值大於0,表示物理內存不夠用或者內存泄露了,要查找耗內存進程解決掉。個人機器內存充裕,一切正常。
so: 每秒虛擬內存寫入磁盤的大小,若是這個值大於0,同上;
bi: 塊設備每秒接收的塊數量,這裏的塊設備是指系統上全部的磁盤和其餘塊設備,默認塊大小是1024byte,我本機上沒什麼IO操做,因此一直是0,可是我曾在處理拷貝大量數據(2-3T)的機器上看過能夠達到140000/s,磁盤寫入速度差很少140M每秒;
bo: 塊設備每秒發送的塊數量,例如咱們讀取文件,bo就要大於0。bi和bo通常都要接近0,否則就是IO過於頻繁,須要調整;
in: 每秒CPU的中斷次數,包括時間中斷;
cs: 每秒上下文切換次數,例如咱們調用系統函數,就要進行上下文切換,線程的切換,也要進程上下文切換,這個值要越小越好,太大了,要考慮調低線程或者進程的數目,例如在apache和nginx這種web服務器中,咱們通常作性能測試時會進行幾千併發甚至幾萬併發的測試,選擇web服務器的進程能夠由進程或者線程的峯值一直下調,壓測,直到cs到一個比較小的值,這個進程和線程數就是比較合適的值了。系統調用也是,每次調用系統函數,咱們的代碼就會進入內核空間,致使上下文切換,這個是很耗資源,也要儘可能避免頻繁調用系統函數。上下文切換次數過多表示你的CPU大部分浪費在上下文切換,致使CPU幹正經事的時間少了,CPU沒有充分利用,是不可取的。
st: cpu在虛擬化環境上在其餘租戶上的開銷;
mpstat:
多處理器統計信息工具,可以報告每一個CPU的統計信息。
[root@zbredis-30104 ~]# mpstat -P ALL 1 Linux 2.6.32-573.el6.x86_64 (zbredis-30104) 09/14/2017 _x86_64_ (12 CPU) 03:14:03 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle 03:14:04 PM all 0.00 0.00 0.08 0.00 0.00 0.00 0.00 0.00 99.92 03:14:04 PM 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 5 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 6 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 7 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 8 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 9 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 10 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 03:14:04 PM 11 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
提示:
irq: 硬件中斷CPU用量;
sofr: 軟件中斷CPU用量;
steal: 耗費在服務其餘租戶的時間;
guest: 花在訪客虛擬機的時間;
重要關注列有%user/%sys/%idle。顯示了每一個CPU的用量以及用戶態和內核態的時間比例。能夠根據這些值查看那些跑到100%使用率(%user + %sys)的CPU,而其餘CPU並未跑滿多是由單線程應用程序的負載或者設備中斷映射形成。
sar:
系統活動報告器。用來觀察當前的活動,以及配置用以歸檔和報告歷史統計信息。基本上全部資源使用的信息,它都可以查看到。具體的參數說明以下所示:
-A: 全部報告的總和,相似"-bBdqrRSuvwWy -I SUM -I XALL -n ALL -u ALL -P ALL"參數一塊兒使用;
-b: 顯示I/O和傳輸速率的統計信息;
-B:顯示分頁狀態;
-d:硬盤使用報告;
-r:內存和交換空間的使用統計;
-g:串口I/O的狀況;
-b:緩衝區使用狀況;
-a:文件讀寫狀況;
-c:系統調用狀況;
-n: 統計網絡信息;
-q:報告隊列長度和系統平均負載;
-R:進程的活動狀況;
-y:終端設備活動狀況;
-w:系統交換活動;
-x { pid | SELF | ALL }:報告指定進程ID的統計信息,SELF關鍵字是sar進程自己的統計,ALL關鍵字是全部系統進程的統計;
經常使用參數組合:
查看CPU:
總體CPU統計— sar -u 3 2,表示採樣時間爲3秒,採樣次數爲2次;
各個CPU統計— sar -P ALL 1 1,表示採樣時間爲1秒,次數爲1次;
1. 若 %iowait 的值太高,表示硬盤存在I/O瓶頸;
2. 若 %idle 的值高但系統響應慢時,有多是 CPU 等待分配內存,此時應加大內存容量;
3. 若 %idle 的值持續低於1,則系統的 CPU 處理能力相對較低,代表系統中最須要解決的資源是 CPU;
查看內存:
查看內存使用狀況 - sar -r 1 2
kbcommit:保證當前系統所須要的內存,即爲了確保不溢出而須要的內存(RAM+swap);
%commit:這個值是kbcommit與內存總量(包括swap)的一個百分比;
pidstat:主要用於監控所有或指定進程佔用系統資源的狀況,如CPU,內存、設備IO、任務切換、線程等。
cpu使用狀況統計
執行 "pidstat -u" 與單獨執行 "pidstat"
內存使用狀況統計
pidstat -r -p PID 1
minflt/s: 每秒次缺頁錯誤次數(minor page faults),次缺頁錯誤次數意即虛擬內存地址映射成物理內存地址產生的page fault次數;
majflt/s: 每秒主缺頁錯誤次數(major page faults),當虛擬內存地址映射成物理內存地址時,相應的page在swap中,這樣的page fault爲major page fault,通常在內存使用緊張時產生;
IO狀況統計
pidstat -d 1 2
關於CPU方面的優化
1.編譯器優化
2.調度優先級和調度類(設置nice值)
例如,nice -n 19 command
renice 更改已經運行進程的優先級;
chrt 命令顯示並直接修改優先級和調度策略;
3.進程綁定(一個進程能夠綁定在一個或者多個CPU上)
例如,taskset -pc 0-3 10790
4.獨佔CPU 5.BIOS調優 啓用睿頻