<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Linux 性能優(yōu)化的全景指南,都在這一篇里了,建議收藏~

          共 22122字,需瀏覽 45分鐘

           ·

          2022-11-18 23:03

          Linux 性能優(yōu)化

          性能優(yōu)化

          性能指標

          高并發(fā)和響應快對應著性能優(yōu)化的兩個核心指標:吞吐和延時

          • 應用負載角度:直接影響了產(chǎn)品終端的用戶體驗
          • 系統(tǒng)資源角度:資源使用率、飽和度等
          性能問題的本質(zhì)就是系統(tǒng)資源已經(jīng)到達瓶頸,但請求的處理還不夠快,無法支撐更多的請求。性能分析實際上就是找出應用或系統(tǒng)的瓶頸,設法去避免或緩解它們。
          • 選擇指標評估應用程序和系統(tǒng)性能

          • 為應用程序和系統(tǒng)設置性能目標

          • 進行性能基準測試

          • 性能分析定位瓶頸

          • 性能監(jiān)控和告警

          對于不同的性能問題要選取不同的性能分析工具。下面是常用的Linux Performance Tools以及對應分析的性能問題類型。

          到底應該怎么理解”平均負載”

          平均負載:單位時間內(nèi),系統(tǒng)處于可運行狀態(tài)和不可中斷狀態(tài)的平均進程數(shù),也就是平均活躍進程數(shù)。它和我們傳統(tǒng)意義上理解的CPU使用率并沒有直接關(guān)系。
          其中不可中斷進程是正處于內(nèi)核態(tài)關(guān)鍵流程中的進程(如常見的等待設備的I/O響應)。不可中斷狀態(tài)實際上是系統(tǒng)對進程和硬件設備的一種保護機制。

          平均負載多少時合理

          實際生產(chǎn)環(huán)境中將系統(tǒng)的平均負載監(jiān)控起來,根據(jù)歷史數(shù)據(jù)判斷負載的變化趨勢。當負載存在明顯升高趨勢時,及時進行分析和調(diào)查。當然也可以當設置閾值(如當平均負載高于CPU數(shù)量的70%時)
          現(xiàn)實工作中我們會經(jīng)常混淆平均負載和CPU使用率的概念,其實兩者并不完全對等:
          • CPU 密集型進程,大量 CPU 使用會導致平均負載升高,此時兩者一致
          • I/O 密集型進程,等待 I/O 也會導致平均負載升高,此時 CPU 使用率并不一定高
          • 大量等待 CPU 的進程調(diào)度會導致平均負載升高,此時 CPU 使用率也會比較高
          平均負載高時可能是 CPU 密集型進程導致,也可能是 I/O 繁忙導致。具體分析時可以結(jié)合 mpstat/pidstat 工具輔助分析負載來源。

          CPU

          CPU上下文切換(上)

          CPU 上下文切換,就是把前一個任務的 CPU 上下文(CPU 寄存器和 PC)保存起來,然后加載新任務的上下文到這些寄存器和程序計數(shù)器,最后再跳轉(zhuǎn)到程序計數(shù)器所指的位置,運行新任務。其中,保存下來的上下文會存儲在系統(tǒng)內(nèi)核中,待任務重新調(diào)度執(zhí)行時再加載,保證原來的任務狀態(tài)不受影響。

          按照任務類型,CPU 上下文切換分為:

          • 進程上下文切換

          • 線程上下文切換

          • 中斷上下文切換

          進程上下文切換

          Linux 進程按照等級權(quán)限將進程的運行空間分為內(nèi)核空間和用戶空間。從用戶態(tài)向內(nèi)核態(tài)轉(zhuǎn)變時需要通過系統(tǒng)調(diào)用來完成。

          一次系統(tǒng)調(diào)用過程其實進行了兩次 CPU 上下文切換:

          • CPU 寄存器中用戶態(tài)的指令位置先保存起來,CPU 寄存器更新為內(nèi)核態(tài)指令的位置,跳轉(zhuǎn)到內(nèi)核態(tài)運行內(nèi)核任務;

          • 系統(tǒng)調(diào)用結(jié)束后,CPU 寄存器恢復原來保存的用戶態(tài)數(shù)據(jù),再切換到用戶空間繼續(xù)運行。

          系統(tǒng)調(diào)用過程中并不會涉及虛擬內(nèi)存等進程用戶態(tài)資源,也不會切換進程。和傳統(tǒng)意義上的進程上下文切換不同。因此系統(tǒng)調(diào)用通常稱為特權(quán)模式切換。

          進程是由內(nèi)核管理和調(diào)度的,進程上下文切換只能發(fā)生在內(nèi)核態(tài)。因此相比系統(tǒng)調(diào)用來說,在保存當前進程的內(nèi)核狀態(tài)和CPU寄存器之前,需要先把該進程的虛擬內(nèi)存,棧保存下來。再加載新進程的內(nèi)核態(tài)后,還要刷新進程的虛擬內(nèi)存和用戶棧。

          進程只有在調(diào)度到CPU上運行時才需要切換上下文,有以下幾種場景:CPU時間片輪流分配,系統(tǒng)資源不足導致進程掛起,進程通過sleep函數(shù)主動掛起,高優(yōu)先級進程搶占時間片,硬件中斷時CPU上的進程被掛起轉(zhuǎn)而執(zhí)行內(nèi)核中的中斷服務。

          線程上下文切換

          線程上下文切換分為兩種:

          • 前后線程同屬于一個進程,切換時虛擬內(nèi)存資源不變,只需要切換線程的私有數(shù)據(jù),寄存器等;

          • 前后線程屬于不同進程,與進程上下文切換相同。

          同進程的線程切換消耗資源較少,這也是多線程的優(yōu)勢。

          中斷上下文切換

          中斷上下文切換并不涉及到進程的用戶態(tài),因此中斷上下文只包括內(nèi)核態(tài)中斷服務程序執(zhí)行所必須的狀態(tài)(CPU寄存器,內(nèi)核堆棧,硬件中斷參數(shù)等)。

          中斷處理優(yōu)先級比進程高,所以中斷上下文切換和進程上下文切換不會同時發(fā)生

          CPU上下文切換(下)

          通過 vmstat 可以查看系統(tǒng)總體的上下文切換情況

          vmstat 5         #每隔5s輸出一組數(shù)據(jù)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 103388 145412 511056    0    0    18    60    1    1  2  1 96  0  0 0  0      0 103388 145412 511076    0    0     0     2  450 1176  1  1 99  0  0 0  0      0 103388 145412 511076    0    0     0     8  429 1135  1  1 98  0  0 0  0      0 103388 145412 511076    0    0     0     0  431 1132  1  1 98  0  0 0  0      0 103388 145412 511076    0    0     0    10  467 1195  1  1 98  0  0 1  0      0 103388 145412 511076    0    0     0     2  426 1139  1  0 99  0  0 4  0      0  95184 145412 511108    0    0     0    74  500 1228  4  1 94  0  0 0  0      0 103512 145416 511076    0    0     0   455  723 1573 12  3 83  2  0
          • cs (context switch) 每秒上下文切換次數(shù)

          • in (interrupt) 每秒中斷次數(shù)

          • r (runnning or runnable)就緒隊列的長度,正在運行和等待CPU的進程數(shù)

          • b (Blocked) 處于不可中斷睡眠狀態(tài)的進程數(shù)

          要查看每個進程的詳細情況,需要使用pidstat來查看每個進程上下文切換情況

          pidstat -w 514時51分16秒   UID       PID   cswch/s nvcswch/s  Command14時51分21秒     0         1      0.80      0.00  systemd14時51分21秒     0         6      1.40      0.00  ksoftirqd/014時51分21秒     0         9     32.67      0.00  rcu_sched14時51分21秒     0        11      0.40      0.00  watchdog/014時51分21秒     0        32      0.20      0.00  khugepaged14時51分21秒     0       271      0.20      0.00  jbd2/vda1-814時51分21秒     0      1332      0.20      0.00  argusagent14時51分21秒     0      5265     10.02      0.00  AliSecGuard14時51分21秒     0      7439      7.82      0.00  kworker/0:214時51分21秒     0      7906      0.20      0.00  pidstat14時51分21秒     0      8346      0.20      0.00  sshd14時51分21秒     0     20654      9.82      0.00  AliYunDun14時51分21秒     0     25766      0.20      0.00  kworker/u2:114時51分21秒     0     28603      1.00      0.00  python3
          • cswch 每秒自愿上下文切換次數(shù)(進程無法獲取所需資源導致的上下文切換)

          • nvcswch 每秒非自愿上下文切換次數(shù)(時間片輪流等系統(tǒng)強制調(diào)度)

          vmstat 1 1    #新終端觀察上下文切換情況此時發(fā)現(xiàn)cs數(shù)據(jù)明顯升高,同時觀察其他指標:r列:遠超系統(tǒng)CPU個數(shù),說明存在大量CPU競爭us和sy列:sy列占比80%,說明CPU主要被內(nèi)核占用in列:中斷次數(shù)明顯上升,說明中斷處理也是潛在問題
          說明運行/等待CPU的進程過多,導致大量的上下文切換,上下文切換導致系統(tǒng)的CPU占用率高
          pidstat -w -u 1  #查看到底哪個進程導致的問題

          從結(jié)果中看出是 sysbench 導致 CPU 使用率過高,但是 pidstat 輸出的上下文次數(shù)加起來也并不多。分析 sysbench 模擬的是線程的切換,因此需要在 pidstat 后加 -t 參數(shù)查看線程指標。

          另外對于中斷次數(shù)過多,我們可以通過 /proc/interrupts 文件讀取
          watch -d cat /proc/interrupts

          發(fā)現(xiàn)次數(shù)變化速度最快的是重調(diào)度中斷(RES),該中斷用來喚醒空閑狀態(tài)的CPU來調(diào)度新的任務運行。分析還是因為過多任務的調(diào)度問題,和上下文切換分析一致。

          某個應用的CPU使用率達到100%,怎么辦?

          Linux作為多任務操作系統(tǒng),將CPU時間劃分為很短的時間片,通過調(diào)度器輪流分配給各個任務使用。為了維護CPU時間,Linux通過事先定義的節(jié)拍率,觸發(fā)時間中斷,并使用全局變了jiffies記錄開機以來的節(jié)拍數(shù)。時間中斷發(fā)生一次該值+1.

          CPU使用率,除了空閑時間以外的其他時間占總CPU時間的百分比。可以通過/proc/stat中的數(shù)據(jù)來計算出CPU使用率。因為/proc/stat時開機以來的節(jié)拍數(shù)累加值,計算出來的是開機以來的平均CPU使用率,一般意義不大。可以間隔取一段時間的兩次值作差來計算該段時間內(nèi)的平均CPU使用率。性能分析工具給出的都是間隔一段時間的平均CPU使用率,要注意間隔時間的設置。

          CPU使用率可以通過top 或 ps來查看。分析進程的CPU問題可以通過perf,它以性能事件采樣為基礎(chǔ),不僅可以分析系統(tǒng)的各種事件和內(nèi)核性能,還可以用來分析指定應用程序的性能問題。

          perf top / perf record / perf report (-g 開啟調(diào)用關(guān)系的采樣)

          sudo docker run --name nginx -p 10000:80 -itd feisky/nginxsudo docker run --name phpfpm -itd --network container:nginx feisky/php-fpm
          ab -c 10 -n 100 http://XXX.XXX.XXX.XXX:10000/ #測試Nginx服務性能

          發(fā)現(xiàn)此時每秒可承受請求給長少,此時將測試的請求數(shù)從100增加到10000。在另外一個終端運行top查看每個CPU的使用率。發(fā)現(xiàn)系統(tǒng)中幾個php-fpm進程導致CPU使用率驟升。

          接著用perf來分析具體是php-fpm中哪個函數(shù)導致該問題。

          perf top -g -p XXXX #對某一個php-fpm進程進行分析
          發(fā)現(xiàn)其中 sqrt 和 add_function 占用 CPU 過多, 此時查看源碼找到原來是sqrt中在發(fā)布前沒有刪除測試代碼段,存在一個百萬次的循環(huán)導致。將該無用代碼刪除后發(fā)現(xiàn)nginx負載能力明顯提升

          系統(tǒng)的CPU使用率很高,為什么找不到高CPU的應用?

          sudo docker run --name nginx -p 10000:80 -itd feisky/nginx:spsudo docker run --name phpfpm -itd --network container:nginx feisky/php-fpm:spab -c 100 -n 1000 http://XXX.XXX.XXX.XXX:10000/ #并發(fā)100個請求測試
          實驗結(jié)果中每秒請求數(shù)依舊不高,我們將并發(fā)請求數(shù)降為5后,nginx負載能力依舊很低。
          此時用top和pidstat發(fā)現(xiàn)系統(tǒng)CPU使用率過高,但是并沒有發(fā)現(xiàn)CPU使用率高的進程。
          出現(xiàn)這種情況一般時我們分析時遺漏的什么信息,重新運行top命令并觀察一會。發(fā)現(xiàn)就緒隊列中處于Running狀態(tài)的進行過多,超過了我們的并發(fā)請求次數(shù)5. 再仔細查看進程運行數(shù)據(jù),發(fā)現(xiàn)nginx和php-fpm都處于sleep狀態(tài),真正處于運行的卻是幾個stress進程。
          下一步就利用pidstat分析這幾個stress進程,發(fā)現(xiàn)沒有任何輸出。用ps aux交叉驗證發(fā)現(xiàn)依舊不存在該進程。說明不是工具的問題。再top查看發(fā)現(xiàn)stress進程的進程號變化了,此時有可能時以下兩種原因?qū)е拢?/span>
          • 進程不停的崩潰重啟(如段錯誤/配置錯誤等),此時進程退出后可能又被監(jiān)控系統(tǒng)重啟;
          • 短時進程導致,即其他應用內(nèi)部通過 exec 調(diào)用的外面命令,這些命令一般只運行很短時間就結(jié)束,很難用top這種間隔較長的工具來發(fā)現(xiàn)

          可以通過pstree來查找 stress 的父進程,找出調(diào)用關(guān)系。

          pstree | grep stress

          發(fā)現(xiàn)是php-fpm調(diào)用的該子進程,此時去查看源碼可以看出每個請求都會調(diào)用一個stress命令來模擬I/O壓力。之前top顯示的結(jié)果是CPU使用率升高,是否真的是由該stress命令導致的,還需要繼續(xù)分析。代碼中給每個請求加了verbose=1的參數(shù)后可以查看stress命令的輸出,在中斷測試該命令結(jié)果顯示stress命令運行時存在因權(quán)限問題導致的文件創(chuàng)建失敗的bug。

          此時依舊只是猜測,下一步繼續(xù)通過perf工具來分析。性能報告顯示確實時stress占用了大量的CPU,通過修復權(quán)限問題來優(yōu)化解決即可。

          系統(tǒng)中出現(xiàn)大量不可中斷進程和僵尸進程怎么辦?

          進程狀態(tài)

          R Running/Runnable,表示進程在CPU的就緒隊列中,正在運行或者等待運行;
          D Disk Sleep,不可中斷狀態(tài)睡眠,一般表示進程正在跟硬件交互,并且交互過程中不允許被其他進程中斷;
          Z Zombie,僵尸進程,表示進程實際上已經(jīng)結(jié)束,但是父進程還沒有回收它的資源;
          S Interruptible Sleep,可中斷睡眠狀態(tài),表示進程因為等待某個事件而被系統(tǒng)掛起,當?shù)却录l(fā)生則會被喚醒并進入R狀態(tài);
          I Idle,空閑狀態(tài),用在不可中斷睡眠的內(nèi)核線程上。該狀態(tài)不會導致平均負載升高;
          T Stop/Traced,表示進程處于暫停或跟蹤狀態(tài)(SIGSTOP/SIGCONT, GDB調(diào)試);
          X Dead,進程已經(jīng)消亡,不會在top/ps中看到。

          對于不可中斷狀態(tài),一般都是在很短時間內(nèi)結(jié)束,可忽略。但是如果系統(tǒng)或硬件發(fā)生故障,進程可能會保持不可中斷狀態(tài)很久,甚至系統(tǒng)中出現(xiàn)大量不可中斷狀態(tài),此時需注意是否出現(xiàn)了I/O性能問題。

          僵尸進程一般多進程應用容易遇到,父進程來不及處理子進程狀態(tài)時子進程就提前退出,此時子進程就變成了僵尸進程。大量的僵尸進程會用盡PID進程號,導致新進程無法建立。

          磁盤O_DIRECT問題

          sudo docker run --privileged --name=app -itd feisky/app:iowaitps aux | grep '/app'
          可以看到此時有多個app進程運行,狀態(tài)分別時Ss+和D+。其中后面s表示進程是一個會話的領(lǐng)導進程,+號表示前臺進程組。
          其中進程組表示一組相互關(guān)聯(lián)的進程,子進程是父進程所在組的組員。會話指共享同一個控制終端的一個或多個進程組。
          用top查看系統(tǒng)資源發(fā)現(xiàn):1)平均負載在逐漸增加,且1分鐘內(nèi)平均負載達到了CPU個數(shù),說明系統(tǒng)可能已經(jīng)有了性能瓶頸;2)僵尸進程比較多且在不停增加;3)us和sys CPU使用率都不高,iowait卻比較高;4)每個進程CPU使用率也不高,但有兩個進程處于D狀態(tài),可能在等待IO。
          分析目前數(shù)據(jù)可知:iowait過高導致系統(tǒng)平均負載升高,僵尸進程不斷增長說明有程序沒能正確清理子進程資源。
          用dstat來分析,因為它可以同時查看CPU和I/O兩種資源的使用情況,便于對比分析。
          dstat 1 10    #間隔1秒輸出10組數(shù)據(jù)
          可以看到當wai(iowait)升高時磁盤請求read都會很大,說明iowait的升高和磁盤的讀請求有關(guān)。接下來分析到底時哪個進程在讀磁盤。

          之前 Top 查看的處于 D 狀態(tài)的進程號,用 pidstat -d -p XXX 展示進程的 I/O 統(tǒng)計數(shù)據(jù)。發(fā)現(xiàn)處于 D 狀態(tài)的進程都沒有任何讀寫操作。在用 pidstat -d 查看所有進程的 I/O統(tǒng)計數(shù)據(jù),看到 app 進程在進行磁盤讀操作,每秒讀取 32MB 的數(shù)據(jù)。進程訪問磁盤必須使用系統(tǒng)調(diào)用處于內(nèi)核態(tài),接下來重點就是找到app進程的系統(tǒng)調(diào)用。

          sudo strace -p XXX #對app進程調(diào)用進行跟蹤
          報錯沒有權(quán)限,因為已經(jīng)時 root 權(quán)限了。所以遇到這種情況,首先要檢查進程狀態(tài)是否正常。ps 命令查找該進程已經(jīng)處于Z狀態(tài),即僵尸進程。
          這種情況下top pidstat之類的工具無法給出更多的信息,此時像第5篇一樣,用 perf record -dperf report 進行分析,查看app進程調(diào)用棧。
          看到 app 確實在通過系統(tǒng)調(diào)用 sys_read() 讀取數(shù)據(jù),并且從 new_sync_readblkdev_direct_IO看出進程時進行直接讀操作,請求直接從磁盤讀,沒有通過緩存導致iowait升高。
          通過層層分析后,root cause 是 app 內(nèi)部進行了磁盤的直接I/O。然后定位到具體代碼位置進行優(yōu)化即可。

          僵尸進程

          上述優(yōu)化后 iowait 顯著下降,但是僵尸進程數(shù)量仍舊在增加。首先要定位僵尸進程的父進程,通過pstree -aps XXX,打印出該僵尸進程的調(diào)用樹,發(fā)現(xiàn)父進程就是app進程。
          查看app代碼,看看子進程結(jié)束的處理是否正確(是否調(diào)用wait()/waitpid(),有沒有注冊SIGCHILD信號的處理函數(shù)等)。
          碰到iowait升高時,先用dstat pidstat等工具確認是否存在磁盤I/O問題,再找是哪些進程導致I/O,不能用strace直接分析進程調(diào)用時可以通過perf工具分析。
          對于僵尸問題,用pstree找到父進程,然后看源碼檢查子進程結(jié)束的處理邏輯即可。

          CPU性能指標

          • CPU使用率

            • 用戶CPU使用率, 包括用戶態(tài)(user)和低優(yōu)先級用戶態(tài)(nice). 該指標過高說明應用程序比較繁忙.

            • 系統(tǒng)CPU使用率, CPU在內(nèi)核態(tài)運行的時間百分比(不含中斷). 該指標高說明內(nèi)核比較繁忙.

            • 等待I/O的CPU使用率, iowait, 該指標高說明系統(tǒng)與硬件設備I/O交互時間比較長.

            • 軟/硬中斷CPU使用率, 該指標高說明系統(tǒng)中發(fā)生大量中斷.

            • steal CPU / guest CPU, 表示虛擬機占用的CPU百分比.

          • 平均負載

            • 理想情況下平均負載等于邏輯CPU個數(shù),表示每個CPU都被充分利用. 若大于則說明系統(tǒng)負載較重.

          • 進程上下文切換

            • 包括無法獲取資源的自愿切換和系統(tǒng)強制調(diào)度時的非自愿切換. 上下文切換本身是保證Linux正常運行的一項核心功能. 過多的切換則會將原本運行進程的CPU時間消耗在寄存器,內(nèi)核占及虛擬內(nèi)存等數(shù)據(jù)保存和恢復上

          • CPU緩存命中率

            • CPU緩存的復用情況,命中率越高性能越好. 其中L1/L2常用在單核,L3則用在多核中

          性能工具

          • 平均負載案例

            • 先用uptime查看系統(tǒng)平均負載

            • 判斷負載在升高后再用mpstat和pidstat分別查看每個CPU和每個進程CPU使用情況.找出導致平均負載較高的進程.

          • 上下文切換案例

            • 先用vmstat查看系統(tǒng)上下文切換和中斷次數(shù)

            • 再用pidstat觀察進程的自愿和非自愿上下文切換情況

            • 最后通過pidstat觀察線程的上下文切換情況

          • 進程CPU使用率高案例

            • 先用top查看系統(tǒng)和進程的CPU使用情況,定位到進程

            • 再用perf top觀察進程調(diào)用鏈,定位到具體函數(shù)

          • 系統(tǒng)CPU使用率高案例

            • 先用top查看系統(tǒng)和進程的CPU使用情況,top/pidstat都無法找到CPU使用率高的進程

            • 重新審視top輸出

            • 從CPU使用率不高,但是處于Running狀態(tài)的進程入手

            • perf record/report發(fā)現(xiàn)短時進程導致 (execsnoop工具)

          • 不可中斷和僵尸進程案例

            • 先用top觀察iowait升高,發(fā)現(xiàn)大量不可中斷和僵尸進程

            • strace無法跟蹤進程系統(tǒng)調(diào)用

            • perf分析調(diào)用鏈發(fā)現(xiàn)根源來自磁盤直接I/O

          • 軟中斷案例

            • top觀察系統(tǒng)軟中斷CPU使用率高

            • 查看/proc/softirqs找到變化速率較快的幾種軟中斷

            • sar命令發(fā)現(xiàn)是網(wǎng)絡小包問題

            • tcpdump找出網(wǎng)絡幀的類型和來源,確定SYN FLOOD攻擊導致

          根據(jù)不同的性能指標來找合適的工具:

          先運行幾個支持指標較多的工具,如 top/vmstat/pidstat,根據(jù)它們的輸出可以得出是哪種類型的性能問題。定位到進程后再用 strace/perf 分析調(diào)用情況進一步分析。如果是軟中斷導致用 /proc/softirqs

          CPU優(yōu)化

          • 應用程序優(yōu)化

            • 編譯器優(yōu)化:編譯階段開啟優(yōu)化選項,如gcc -O2

            • 算法優(yōu)化

            • 異步處理:避免程序因為等待某個資源而一直阻塞,提升程序的并發(fā)處理能力。(將輪詢替換為事件通知)

            • 多線程代替多進程:減少上下文切換成本

            • 善用緩存:加快程序處理速度

          • 系統(tǒng)優(yōu)化

            • CPU綁定:將進程綁定要1個/多個CPU上,提高CPU緩存命中率,減少CPU調(diào)度帶來的上下文切換

            • CPU獨占:CPU親和性機制來分配進程

            • 優(yōu)先級調(diào)整:使用nice適當降低非核心應用的優(yōu)先級

            • 為進程設置資源顯示: cgroups設置使用上限,防止由某個應用自身問題耗盡系統(tǒng)資源

            • NUMA優(yōu)化: CPU盡可能訪問本地內(nèi)存

            • 中斷負載均衡: irpbalance,將中斷處理過程自動負載均衡到各個CPU上

          • TPS、QPS、系統(tǒng)吞吐量的區(qū)別和理解

            • QPS(TPS)

            • 并發(fā)數(shù)

            • 響應時間

            • QPS(TPS)=并發(fā)數(shù)/平均相應時間

            • 用戶請求服務器

            • 服務器內(nèi)部處理

            • 服務器返回給客戶
              QPS 類似 TPS,但是對于一個頁面的訪問形成一個 TPS,但是一次頁面請求可能包含多次對服務器的請求,可能計入多次 QPS

            • QPS(Queries Per Second)每秒查詢率,一臺服務器每秒能夠響應的查詢次數(shù).

            • TPS(Transactions Per Second)每秒事務數(shù),軟件測試的結(jié)果.

          • 系統(tǒng)吞吐量,包括幾個重要參數(shù):

          內(nèi)存

          Linux內(nèi)存是怎么工作的

          內(nèi)存映射
          大多數(shù)計算機用的主存都是動態(tài)隨機訪問內(nèi)存(DRAM),只有內(nèi)核才可以直接訪問物理內(nèi)存。Linux內(nèi)核給每個進程提供了一個獨立的虛擬地址空間,并且這個地址空間是連續(xù)的。這樣進程就可以很方便的訪問內(nèi)存(虛擬內(nèi)存)。
          虛擬地址空間的內(nèi)部分為內(nèi)核空間和用戶空間兩部分,不同字長的處理器地址空間的范圍不同。32位系統(tǒng)內(nèi)核空間占用1G,用戶空間占3G。64位系統(tǒng)內(nèi)核空間和用戶空間都是128T,分別占內(nèi)存空間的最高和最低處,中間部分為未定義。
          并不是所有的虛擬內(nèi)存都會分配物理內(nèi)存,只有實際使用的才會。分配后的物理內(nèi)存通過內(nèi)存映射管理。為了完成內(nèi)存映射,內(nèi)核為每個進程都維護了一個頁表,記錄虛擬地址和物理地址的映射關(guān)系。頁表實際存儲在CPU的內(nèi)存管理單元MMU中,處理器可以直接通過硬件找出要訪問的內(nèi)存。
          當進程訪問的虛擬地址在頁表中查不到時,系統(tǒng)會產(chǎn)生一個缺頁異常,進入內(nèi)核空間分配物理內(nèi)存,更新進程頁表,再返回用戶空間恢復進程的運行。
          MMU以頁為單位管理內(nèi)存,頁大小4KB。為了解決頁表項過多問題Linux提供了多級頁表和HugePage的機制。
          虛擬內(nèi)存空間分布

          用戶空間內(nèi)存從低到高是五種不同的內(nèi)存段:

          • 只讀段 代碼和常量等

          • 數(shù)據(jù)段 全局變量等

          • 動態(tài)分配的內(nèi)存,從低地址開始向上增長

          • 文件映射 動態(tài)庫、共享內(nèi)存等,從高地址開始向下增長

          • 包括局部變量和函數(shù)調(diào)用的上下文等,棧的大小是固定的。一般8MB

          內(nèi)存分配與回收

          分配

          malloc 對應到系統(tǒng)調(diào)用上有兩種實現(xiàn)方式:

          • brk() 針對小塊內(nèi)存(<128K),通過移動堆頂位置來分配。

            內(nèi)存釋放后不立即歸還內(nèi)存,而是被緩存起來。

          • mmap()針對大塊內(nèi)存(>128K),直接用內(nèi)存映射來分配,即在文件映射段找一塊空閑內(nèi)存分配。

          前者的緩存可以減少缺頁異常的發(fā)生,提高內(nèi)存訪問效率。但是由于內(nèi)存沒有歸還系統(tǒng),在內(nèi)存工作繁忙時,頻繁的內(nèi)存分配/釋放會造成內(nèi)存碎片。

          后者在釋放時直接歸還系統(tǒng),所以每次mmap都會發(fā)生缺頁異常。

          在內(nèi)存工作繁忙時,頻繁內(nèi)存分配會導致大量缺頁異常,使內(nèi)核管理負擔增加。

          上述兩種調(diào)用并沒有真正分配內(nèi)存,這些內(nèi)存只有在首次訪問時,才通過缺頁異常進入內(nèi)核中,由內(nèi)核來分配


          回收

          內(nèi)存緊張時,系統(tǒng)通過以下方式來回收內(nèi)存:

          • 回收緩存:LRU算法回收最近最少使用的內(nèi)存頁面;

          • 回收不常訪問內(nèi)存:把不常用的內(nèi)存通過交換分區(qū)寫入磁盤

          • 殺死進程:OOM內(nèi)核保護機制(進程消耗內(nèi)存越大 oom_score 越大,占用 CPU 越多 oom_score 越小,可以通過 /proc 手動調(diào)整 oom_adj)

          echo -16 > /proc/$(pidof XXX)/oom_adj

          如何查看內(nèi)存使用情況

          free來查看整個系統(tǒng)的內(nèi)存使用情況

          top/ps來查看某個進程的內(nèi)存使用情況

          • VIRT 進程的虛擬內(nèi)存大小

          • RES 常駐內(nèi)存的大小,即進程實際使用的物理內(nèi)存大小,不包括swap和共享內(nèi)存

          • SHR 共享內(nèi)存大小,與其他進程共享的內(nèi)存,加載的動態(tài)鏈接庫以及程序代碼段

          • %MEM 進程使用物理內(nèi)存占系統(tǒng)總內(nèi)存的百分比

          怎樣理解內(nèi)存中的Buffer和Cache?

          buffer是對磁盤數(shù)據(jù)的緩存,cache是對文件數(shù)據(jù)的緩存,它們既會用在讀請求也會用在寫請求中

          如何利用系統(tǒng)緩存優(yōu)化程序的運行效率

          緩存命中率

          緩存命中率是指直接通過緩存獲取數(shù)據(jù)的請求次數(shù),占所有請求次數(shù)的百分比。命中率越高說明緩存帶來的收益越高,應用程序的性能也就越好。
          安裝bcc包后可以通過cachestat和cachetop來監(jiān)測緩存的讀寫命中情況。
          安裝pcstat后可以查看文件在內(nèi)存中的緩存大小以及緩存比例
          #首先安裝Goexport GOPATH=~/goexport PATH=~/go/bin:$PATHgo get golang.org/x/sys/unixgo ge github.com/tobert/pcstat/pcstat

          dd緩存加速

          dd if=/dev/sda1 of=file bs=1M count=512 #生產(chǎn)一個512MB的臨時文件echo 3 > /proc/sys/vm/drop_caches #清理緩存pcstat file #確定剛才生成文件不在系統(tǒng)緩存中,此時cached和percent都是0cachetop 5dd if=file of=/dev/null bs=1M #測試文件讀取速度#此時文件讀取性能為30+MB/s,查看cachetop結(jié)果發(fā)現(xiàn)并不是所有的讀都落在磁盤上,讀緩存命中率只有50%。dd if=file of=/dev/null bs=1M #重復上述讀文件測試#此時文件讀取性能為4+GB/s,讀緩存命中率為100%pcstat file #查看文件file的緩存情況,100%全部緩存

          O_DIRECT選項繞過系統(tǒng)緩存

          cachetop 5sudo docker run --privileged --name=app -itd feisky/app:io-directsudo docker logs app #確認案例啟動成功#實驗結(jié)果表明每讀32MB數(shù)據(jù)都要花0.9s,且cachetop輸出中顯示1024次緩存全部命中
          但是憑感覺可知如果緩存命中讀速度不應如此慢,讀次數(shù)時1024,頁大小為4K,五秒的時間內(nèi)讀取了1024*4KB數(shù)據(jù),即每秒0.8MB,和結(jié)果中32MB相差較大。說明該案例沒有充分利用緩存,懷疑系統(tǒng)調(diào)用設置了直接I/O標志繞過系統(tǒng)緩存。因此接下來觀察系統(tǒng)調(diào)用。
          strace -p $(pgrep app)#strace 結(jié)果可以看到openat打開磁盤分區(qū)/dev/sdb1,傳入?yún)?shù)為O_RDONLY|O_DIRECT
          這就解釋了為什么讀32MB數(shù)據(jù)那么慢,直接從磁盤讀寫肯定遠遠慢于緩存。找出問題后我們再看案例的源代碼發(fā)現(xiàn)flags中指定了直接IO標志。刪除該選項后重跑,驗證性能變化。

          內(nèi)存泄漏,如何定位和處理?

          對應用程序來說,動態(tài)內(nèi)存的分配和回收是核心又復雜的一個邏輯功能模塊。管理內(nèi)存的過程中會發(fā)生各種各樣的“事故”:
          • 沒正確回收分配的內(nèi)存,導致了泄漏
          • 訪問的是已分配內(nèi)存邊界外的地址,導致程序異常退出

          內(nèi)存的分配與回收

          虛擬內(nèi)存分布從低到高分別是只讀段,數(shù)據(jù)段,堆,內(nèi)存映射段,棧五部分。其中會導致內(nèi)存泄漏的是:

          • 堆:由應用程序自己來分配和管理,除非程序退出這些堆內(nèi)存不會被系統(tǒng)自動釋放。

          • 內(nèi)存映射段:包括動態(tài)鏈接庫和共享內(nèi)存,其中共享內(nèi)存由程序自動分配和管理

          內(nèi)存泄漏的危害比較大,這些忘記釋放的內(nèi)存,不僅應用程序自己不能訪問,系統(tǒng)也不能把它們再次分配給其他應用。內(nèi)存泄漏不斷累積甚至會耗盡系統(tǒng)內(nèi)存。

          如何檢測內(nèi)存泄漏

          預先安裝systat,docker,bcc

          sudo docker run --name=app -itd feisky/app:mem-leaksudo docker logs appvmstat 3
          可以看到free在不斷下降,buffer和cache基本保持不變。說明系統(tǒng)的內(nèi)存一致在升高。但并不能說明存在內(nèi)存泄漏。此時可以通過memleak工具來跟蹤系統(tǒng)或進程的內(nèi)存分配/釋放請求
          /usr/share/bcc/tools/memleak -a -p $(pidof app)

          從 memleak 輸出可以看到,應用在不停地分配內(nèi)存,并且這些分配的地址并沒有被回收。通過調(diào)用棧看到是 fibonacci 函數(shù)分配的內(nèi)存沒有釋放。定位到源碼后查看源碼來修復增加內(nèi)存釋放函數(shù)即可。

          為什么系統(tǒng)的 Swap 變高

          系統(tǒng)內(nèi)存資源緊張時通過內(nèi)存回收和OOM殺死進程來解決。其中可回收內(nèi)存包括:
          • 緩存/緩沖區(qū),屬于可回收資源,在文件管理中通常叫做文件頁
            • 在應用程序中通過fsync將臟頁同步到磁盤
            • 交給系統(tǒng),內(nèi)核線程pdflush負責這些臟頁的刷新
            • 被應用程序修改過暫時沒寫入磁盤的數(shù)據(jù)(臟頁),要先寫入磁盤然后才能內(nèi)存釋放
          • 內(nèi)存映射獲取的文件映射頁,也可以被釋放掉,下次訪問時從文件重新讀取
          對于程序自動分配的堆內(nèi)存,也就是我們在內(nèi)存管理中的匿名頁,雖然這些內(nèi)存不能直接釋放,但是 Linux 提供了 Swap 機制將不常訪問的內(nèi)存寫入到磁盤來釋放內(nèi)存,再次訪問時從磁盤讀取到內(nèi)存即可。
          Swap原理

          Swap本質(zhì)就是把一塊磁盤空間或者一個本地文件當作內(nèi)存來使用,包括換入和換出兩個過程:

          • 換出:將進程暫時不用的內(nèi)存數(shù)據(jù)存儲到磁盤中,并釋放這些內(nèi)存

          • 換入:進程再次訪問內(nèi)存時,將它們從磁盤讀到內(nèi)存中

          Linux如何衡量內(nèi)存資源是否緊張?

          • 直接內(nèi)存回收新的大塊內(nèi)存分配請求,但剩余內(nèi)存不足。

            此時系統(tǒng)會回收一部分內(nèi)存;

          • kswapd0 內(nèi)核線程定期回收內(nèi)存。

            為了衡量內(nèi)存使用情況,定義了pages_min,pages_low,pages_high 三個閾值,并根據(jù)其來進行內(nèi)存的回收操作。

            • 剩余內(nèi)存 < pages_min,進程可用內(nèi)存耗盡了,只有內(nèi)核才可以分配內(nèi)存

            • pages_min < 剩余內(nèi)存 < pages_low,內(nèi)存壓力較大,kswapd0執(zhí)行內(nèi)存回收,直到剩余內(nèi)存 > pages_high

            • pages_low < 剩余內(nèi)存 < pages_high,內(nèi)存有一定壓力,但可以滿足新內(nèi)存請求

            • 剩余內(nèi)存 > pages_high,說明剩余內(nèi)存較多,無內(nèi)存壓力
              pages_low = pages_min 5 / 4 pages_high = pages_min 3 / 2

          NUMA 與 SWAP
          很多情況下系統(tǒng)剩余內(nèi)存較多,但 SWAP 依舊升高,這是由于處理器的 NUMA 架構(gòu)。
          在NUMA架構(gòu)下多個處理器劃分到不同的 Node,每個Node都擁有自己的本地內(nèi)存空間。在分析內(nèi)存的使用時應該針對每個Node單獨分析
          numactl --hardware #查看處理器在Node的分布情況,以及每個Node的內(nèi)存使用情況
          內(nèi)存三個閾值可以通過 /proc/zoneinfo 來查看,該文件中還包括活躍和非活躍的匿名頁/文件頁數(shù)。
          當某個Node內(nèi)存不足時,系統(tǒng)可以從其他Node尋找空閑資源,也可以從本地內(nèi)存中回收內(nèi)存。通過/proc/sys/vm/zone_raclaim_mode來調(diào)整。
          • 0表示既可以從其他Node尋找空閑資源,也可以從本地回收內(nèi)存

          • 1,2,4 表示只回收本地內(nèi)存,2表示可以會回臟數(shù)據(jù)回收內(nèi)存,4表示可以用Swap方式回收內(nèi)存。

          swappiness
          在實際回收過程中Linux根據(jù) /proc/sys/vm/swapiness 選項來調(diào)整使用Swap的積極程度,從 0-100,數(shù)值越大越積極使用 Swap,即更傾向于回收匿名頁;數(shù)值越小越消極使用 Swap,即更傾向于回收文件頁。
          注意:這只是調(diào)整 Swap 積極程度的權(quán)重,即使設置為0,當剩余內(nèi)存+文件頁小于頁高閾值時,還是會發(fā)生 Swap。

          Swap升高時如何定位分析

          free #首先通過free查看swap使用情況,若swap=0表示未配置Swap#先創(chuàng)建并開啟swapfallocate -l 8G /mnt/swapfilechmod 600 /mnt/swapfilemkswap /mnt/swapfileswapon /mnt/swapfile
          free #再次執(zhí)行free確保Swap配置成功
          dd if=/dev/sda1 of=/dev/null bs=1G count=2048 #模擬大文件讀取sar -r -S 1 #查看內(nèi)存各個指標變化 -r內(nèi)存 -S swap#根據(jù)結(jié)果可以看出,%memused在不斷增長,剩余內(nèi)存kbmemfress不斷減少,緩沖區(qū)kbbuffers不斷增大,由此可知剩余內(nèi)存不斷分配給了緩沖區(qū)#一段時間之后,剩余內(nèi)存很小,而緩沖區(qū)占用了大部分內(nèi)存。此時Swap使用之間增大,緩沖區(qū)和剩余內(nèi)存只在小范圍波動
          停下sar命令cachetop5 #觀察緩存#可以看到dd進程讀寫只有50%的命中率,未命中數(shù)為4w+頁,說明正式dd進程導致緩沖區(qū)使用升高watch -d grep -A 15 ‘Normal’ /proc/zoneinfo #觀察內(nèi)存指標變化#發(fā)現(xiàn)升級內(nèi)存在一個小范圍不停的波動,低于頁低閾值時會突然增大到一個大于頁高閾值的值
          說明剩余內(nèi)存和緩沖區(qū)的波動變化正是由于內(nèi)存回收和緩存再次分配的循環(huán)往復。有時候 Swap 用的多,有時候緩沖區(qū)波動更多。此時查看 swappiness 值為60,是一個相對中和的配置,系統(tǒng)會根據(jù)實際運行情況來選去合適的回收類型。

          如何“快準狠”找到系統(tǒng)內(nèi)存存在的問題

          內(nèi)存性能指標

          • 系統(tǒng)內(nèi)存指標
          • 已用內(nèi)存/剩余內(nèi)存
          • 共享內(nèi)存 (tmpfs實現(xiàn))
          • 可用內(nèi)存:包括剩余內(nèi)存和可回收內(nèi)存
          • 緩存:磁盤讀取文件的頁緩存,slab分配器中的可回收部分
          • 緩沖區(qū):原始磁盤塊的臨時存儲,緩存將要寫入磁盤的數(shù)據(jù)

          進程內(nèi)存指標

          • 虛擬內(nèi)存:5大部分

          • 常駐內(nèi)存:進程實際使用的物理內(nèi)存,不包括Swap和共享內(nèi)存

          • 共享內(nèi)存:與其他進程共享的內(nèi)存,以及動態(tài)鏈接庫和程序的代碼段

          • Swap 內(nèi)存:通過Swap換出到磁盤的內(nèi)存

          缺頁異常
          • 可以直接從物理內(nèi)存中分配,次缺頁異常
          • 需要磁盤 IO 介入(如 Swap),主缺頁異常。此時內(nèi)存訪問會慢很多
          內(nèi)存性能工具

          根據(jù)不同的性能指標來找合適的工具:

          內(nèi)存分析工具包含的性能指標:

          如何迅速分析內(nèi)存的性能瓶頸

          通常先運行幾個覆蓋面比較大的性能工具,如 free,top,vmstat,pidstat 等

          • 先用 free 和 top 查看系統(tǒng)整體內(nèi)存使用情況

          • 再用 vmstat 和 pidstat,查看一段時間的趨勢,從而判斷內(nèi)存問題的類型

          • 最后進行詳細分析,比如內(nèi)存分配分析,緩存/緩沖區(qū)分析,具體進程的內(nèi)存使用分析等

          常見的優(yōu)化思路:

          • 最好禁止 Swap,若必須開啟則盡量降低 swappiness 的值

          • 減少內(nèi)存的動態(tài)分配,如可以用內(nèi)存池,HugePage 等

          • 盡量使用緩存和緩沖區(qū)來訪問數(shù)據(jù)。如用堆棧明確聲明內(nèi)存空間來存儲需要緩存的數(shù)據(jù),或者用 Redis 外部緩存組件來優(yōu)化數(shù)據(jù)的訪問

          • cgroups 等方式來限制進程的內(nèi)存使用情況,確保系統(tǒng)內(nèi)存不被異常進程耗盡

          • /proc/pid/oom_adj 調(diào)整核心應用的 oom_score,保證即使內(nèi)存緊張核心應用也不會被OOM殺死

          vmstat 使用詳解

          vmstat 命令是最常見的 Linux/Unix 監(jiān)控工具,可以展現(xiàn)給定時間間隔的服務器的狀態(tài)值,包括服務器的 CPU 使用率,內(nèi)存使用,虛擬內(nèi)存交換情況,IO讀寫情況。可以看到整個機器的 CPU,內(nèi)存,IO 的使用情況,而不是單單看到各個進程的 CPU 使用率和內(nèi)存使用率(使用場景不一樣)。

          vmstat 2procs -----------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 1379064 282244 11537528    0    0     3   104    0    0  3  0 97  0  0 0  0      0 1372716 282244 11537544    0    0     0    24 4893 8947  1  0 98  0  0 0  0      0 1373404 282248 11537544    0    0     0    96 5105 9278  2  0 98  0  0 0  0      0 1374168 282248 11537556    0    0     0     0 5001 9208  1  0 99  0  0 0  0      0 1376948 282248 11537564    0    0     0    80 5176 9388  2  0 98  0  0 0  0      0 1379356 282256 11537580    0    0     0   202 5474 9519  2  0 98  0  0 1  0      0 1368376 282256 11543696    0    0     0     0 5894 8940 12  0 88  0  0 1  0      0 1371936 282256 11539240    0    0     0 10554 6176 9481 14  1 85  1  0 1  0      0 1366184 282260 11542292    0    0     0  7456 6102 9983  7  1 91  0  0 1  0      0 1353040 282260 11556176    0    0     0 16924 7233 9578 18  1 80  1  0 0  0      0 1359432 282260 11549124    0    0     0 12576 5495 9271  7  0 92  1  0 0  0      0 1361744 282264 11549132    0    0     0    58 8606 15079  4  2 95  0  0 1  0      0 1367120 282264 11549140    0    0     0     2 5716 9205  8  0 92  0  0 0  0      0 1346580 282264 11562644    0    0     0    70 6416 9944 12  0 88  0  0 0  0      0 1359164 282264 11550108    0    0     0  2922 4941 8969  3  0 97  0  0 1  0      0 1353992 282264 11557044    0    0     0     0 6023 8917 15  0 84  0  0
          # 結(jié)果說明- r 表示運行隊列(就是說多少個進程真的分配到CPU),我測試的服務器目前CPU比較空閑,沒什么程序在跑,當這個值超過了CPU數(shù)目,就會出現(xiàn)CPU瓶頸了。這個也和top的負載有關(guān)系,一般負載超過了3就比較高,超過了5就高,超過了10就不正常了,服務器的狀態(tài)很危險。top的負載類似每秒的運行隊列。如果運行隊列過大,表示你的CPU很繁忙,一般會造成CPU使用率很高。
          - b 表示阻塞的進程,這個不多說,進程阻塞,大家懂的。
          - swpd 虛擬內(nèi)存已使用的大小,如果大于0,表示你的機器物理內(nèi)存不足了,如果不是程序內(nèi)存泄露的原因,那么你該升級內(nèi)存了或者把耗內(nèi)存的任務遷移到其他機器。
          - free 空閑的物理內(nèi)存的大小,我的機器內(nèi)存總共8G,剩余3415M。
          - buff Linux/Unix系統(tǒng)是用來存儲,目錄里面有什么內(nèi)容,權(quán)限等的緩存,我本機大概占用300多M
          - cache cache直接用來記憶我們打開的文件,給文件做緩沖,我本機大概占用300多M(這里是Linux/Unix的聰明之處,把空閑的物理內(nèi)存的一部分拿來做文件和目錄的緩存,是為了提高 程序執(zhí)行的性能,當程序使用內(nèi)存時,buffer/cached會很快地被使用。)
          - si 每秒從磁盤讀入虛擬內(nèi)存的大小,如果這個值大于0,表示物理內(nèi)存不夠用或者內(nèi)存泄露了,要查找耗內(nèi)存進程解決掉。我的機器內(nèi)存充裕,一切正常。
          - so 每秒虛擬內(nèi)存寫入磁盤的大小,如果這個值大于0,同上。
          - bi 塊設備每秒接收的塊數(shù)量,這里的塊設備是指系統(tǒng)上所有的磁盤和其他塊設備,默認塊大小是1024byte,我本機上沒什么IO操作,所以一直是0,但是我曾在處理拷貝大量數(shù)據(jù)(2-3T)的機器上看過可以達到140000/s,磁盤寫入速度差不多140M每秒
          - bo 塊設備每秒發(fā)送的塊數(shù)量,例如我們讀取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO過于頻繁,需要調(diào)整。
          - in 每秒CPU的中斷次數(shù),包括時間中斷
          - cs 每秒上下文切換次數(shù),例如我們調(diào)用系統(tǒng)函數(shù),就要進行上下文切換,線程的切換,也要進程上下文切換,這個值要越小越好,太大了,要考慮調(diào)低線程或者進程的數(shù)目,例如在apache和nginx這種web服務器中,我們一般做性能測試時會進行幾千并發(fā)甚至幾萬并發(fā)的測試,選擇web服務器的進程可以由進程或者線程的峰值一直下調(diào),壓測,直到cs到一個比較小的值,這個進程和線程數(shù)就是比較合適的值了。系統(tǒng)調(diào)用也是,每次調(diào)用系統(tǒng)函數(shù),我們的代碼就會進入內(nèi)核空間,導致上下文切換,這個是很耗資源,也要盡量避免頻繁調(diào)用系統(tǒng)函數(shù)。上下文切換次數(shù)過多表示你的CPU大部分浪費在上下文切換,導致CPU干正經(jīng)事的時間少了,CPU沒有充分利用,是不可取的。
          - us 用戶CPU時間,我曾經(jīng)在一個做加密解密很頻繁的服務器上,可以看到us接近100,r運行隊列達到80(機器在做壓力測試,性能表現(xiàn)不佳)。
          - sy 系統(tǒng)CPU時間,如果太高,表示系統(tǒng)調(diào)用時間長,例如是IO操作頻繁。
          - id 空閑CPU時間,一般來說,id + us + sy = 100,一般我認為id是空閑CPU使用率,us是用戶CPU使用率,sy是系統(tǒng)CPU使用率。
          - wt 等待IO CPU時間

          pidstat 使用詳解

          pidstat 主要用于監(jiān)控全部或指定進程占用系統(tǒng)資源的情況,如CPU,內(nèi)存、設備IO、任務切換、線程等。

          使用方法:
          • pidstat –d interval times 統(tǒng)計各個進程的IO使用情況
          • pidstat –u interval times 統(tǒng)計各個進程的CPU統(tǒng)計信息
          • pidstat –r interval times 統(tǒng)計各個進程的內(nèi)存使用信息
          • pidstat -w interval times 統(tǒng)計各個進程的上下文切換
          • p PID 指定PID

          1、統(tǒng)計 IO 使用情況

          pidstat -d 1 10
          03:02:02 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command03:02:03 PM 0 816 0.00 918.81 0.00 jbd2/vda1-803:02:03 PM 0 1007 0.00 3.96 0.00 AliYunDun03:02:03 PM 997 7326 0.00 1904.95 918.81 java03:02:03 PM 997 8539 0.00 3.96 0.00 java03:02:03 PM 0 16066 0.00 35.64 0.00 cmagent
          03:02:03 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command03:02:04 PM 0 816 0.00 1924.00 0.00 jbd2/vda1-803:02:04 PM 997 7326 0.00 11156.00 1888.00 java03:02:04 PM 997 8539 0.00 4.00 0.00 java
          • UID

          • PID

          • kB_rd/s:每秒進程從磁盤讀取的數(shù)據(jù)量 KB 單位 read from disk each second KB

          • kB_wr/s:每秒進程向磁盤寫的數(shù)據(jù)量 KB 單位 write to disk each second KB

          • kB_ccwr/s:每秒進程向磁盤寫入,但是被取消的數(shù)據(jù)量,This may occur when the task truncates some dirty pagecache.

          • iodelay:Block I/O delay,measured in clock ticks

          • Command:進程名 task name

          2、統(tǒng)計 CPU 使用情況

          # 統(tǒng)計CPUpidstat -u 1 1003:03:33 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command03:03:34 PM     0      2321    3.96    0.00    0.00    3.96     0  ansible03:03:34 PM     0      7110    0.00    0.99    0.00    0.99     4  pidstat03:03:34 PM   997      8539    0.99    0.00    0.00    0.99     5  java03:03:34 PM   984     15517    0.99    0.00    0.00    0.99     5  java03:03:34 PM     0     24406    0.99    0.00    0.00    0.99     5  java03:03:34 PM     0     32158    3.96    0.00    0.00    3.96     2  ansible
          • UID

          • PID

          • %usr: 進程在用戶空間占用 cpu 的百分比

          • %system: 進程在內(nèi)核空間占用 CPU 百分比

          • %guest: 進程在虛擬機占用 CPU 百分比

          • %wait: 進程等待運行的百分比

          • %CPU: 進程占用 CPU 百分比

          • CPU: 處理進程的 CPU 編號

          • Command: 進程名

          3、統(tǒng)計內(nèi)存使用情況

          # 統(tǒng)計內(nèi)存pidstat -r 1 10Average:      UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  CommandAverage:        0         1      0.20      0.00  191256   3064   0.01  systemdAverage:        0      1007      1.30      0.00  143256  22720   0.07  AliYunDunAverage:        0      6642      0.10      0.00 6301904 107680   0.33  javaAverage:      997      7326     10.89      0.00 13468904 8395848  26.04  javaAverage:        0      7795    348.15      0.00  108376   1233   0.00  pidstatAverage:      997      8539      0.50      0.00 8242256 2062228   6.40  javaAverage:      987      9518      0.20      0.00 6300944 1242924   3.85  javaAverage:        0     10280      3.70      0.00  807372   8344   0.03  aliyun-serviceAverage:      984     15517      0.40      0.00 6386464 1464572   4.54  javaAverage:        0     16066    236.46      0.00 2678332  71020   0.22  cmagentAverage:      995     20955      0.30      0.00 6312520 1408040   4.37  javaAverage:      995     20956      0.20      0.00 6093764 1505028   4.67  javaAverage:        0     23936      0.10      0.00 5302416 110804   0.34  javaAverage:        0     24406      0.70      0.00 10211672 2361304   7.32  javaAverage:        0     26870      1.40      0.00 1470212  36084   0.11  promtail
          • UID
          • PID
          • Minflt/s : 每秒次缺頁錯誤次數(shù) (minor page faults),虛擬內(nèi)存地址映射成物理內(nèi)存地址產(chǎn)生的 page fault 次數(shù)
          • Majflt/s : 每秒主缺頁錯誤次數(shù) (major page faults), 虛擬內(nèi)存地址映射成物理內(nèi)存地址時,相應 page 在 swap 中
          • VSZ virtual memory usage : 該進程使用的虛擬內(nèi)存 KB 單位
          • RSS : 該進程使用的物理內(nèi)存 KB 單位
          • %MEM : 內(nèi)存使用率
          • Command : 該進程的命令 task name

          4、查看具體進程使用情況

          pidstat -T ALL -r -p 20955 1 1003:12:16 PM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command03:12:17 PM   995     20955      0.00      0.00 6312520 1408040   4.37  java
          03:12:16 PM UID PID minflt-nr majflt-nr Command03:12:17 PM 995 20955 0 0 java

          來源:https://www.ctq6.cn/linux%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/

          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本无码中文字幕综合一区 | 免费看黄色视频在线观看 | 91香蕉国产一区二区 | 无码电影中文字幕 | 息子交尾一区二区三区 |