1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        ?Linux CPU 性能優(yōu)化指南

        共 15378字,需瀏覽 31分鐘

         ·

        2020-08-14 20:23




        本文作者:allenxguo,騰訊 QQ 音樂(lè)后臺(tái)開發(fā)工程師

        本文主要幫助理解 CPU 相關(guān)的性能指標(biāo),常見(jiàn)的 CPU 性能問(wèn)題以及解決方案梳理。


        系統(tǒng)平均負(fù)載

        簡(jiǎn)介

        系統(tǒng)平均負(fù)載:是處于可運(yùn)行或不可中斷狀態(tài)的平均進(jìn)程數(shù)。

        可運(yùn)行進(jìn)程:使用 CPU 或等待使用 CPU 的進(jìn)程

        不可中斷狀態(tài)進(jìn)程:正在等待某些 IO 訪問(wèn),一般是和硬件交互,不可被打斷(不可被打斷的原因是為了保護(hù)系統(tǒng)數(shù)據(jù)一致,防止數(shù)據(jù)讀取錯(cuò)誤)

        查看系統(tǒng)平均負(fù)載

        首先top命令查看進(jìn)程運(yùn)行狀態(tài),如下:

         PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND10760 user   20   0 3061604  84832   5956 S  82.4  0.6 126:47.61 Process29424 user   20   0   54060   2668   1360 R  17.6  0.0   0:00.03 **top**

        程序狀態(tài)Status進(jìn)程可運(yùn)行狀態(tài)R不可中斷運(yùn)行D(后續(xù)講解 top 時(shí)會(huì)詳細(xì)說(shuō)明)

        top查看系統(tǒng)平均負(fù)載:

        top - 13:09:42 up 888 days, 21:32,  8 users,  load average: 19.95, 14.71, 14.01Tasks: 642 total,   2 running, 640 sleeping,   0 stopped,   0 zombie%Cpu0  : 37.5 us, 27.6 sy,  0.0 ni, 30.9 id,  0.0 wa,  0.0 hi,  3.6 si,  0.3 st%Cpu1  : 34.1 us, 31.5 sy,  0.0 ni, 34.1 id,  0.0 wa,  0.0 hi,  0.4 si,  0.0 st...KiB Mem : 14108016 total,  2919496 free,  6220236 used,  4968284 buff/cacheKiB Swap:        0 total,        0 free,        0 used.  6654506 avail Mem

        這里的load average就表示系統(tǒng)最近 1 分鐘、5 分鐘、15 分鐘的系統(tǒng)瓶頸負(fù)載。

        uptime查看系統(tǒng)瓶頸負(fù)載

        [root /home/user]# uptime 13:11:01 up 888 days, 21:33,  8 users,  load average: 17.20, 14.85, 14.10
        查看 CPU 核信息

        系統(tǒng)平均負(fù)載和 CPU 核數(shù)密切相關(guān),我們可以通過(guò)以下命令查看當(dāng)前機(jī)器 CPU 信息:

        lscpu查看 CPU 信息:

        [root@Tencent-SNG /home/user_00]# lscpuArchitecture:          x86_64CPU op-mode(s):        32-bit, 64-bitByte Order:            Little EndianCPU(s):                8...L1d cache:             32KL1i cache:             32KL2 cache:              4096KNUMA node0 CPU(s):     0-7  // NUMA架構(gòu)信息

        cat /proc/cpuinfo查看每個(gè) CPU 核的信息:

        processor       : 7   // 核編號(hào)7vendor_id       : GenuineIntelcpu family      : 6model           : 6...
        系統(tǒng)平均負(fù)載升高的原因

        一般來(lái)說(shuō),系統(tǒng)平均負(fù)載升高意味著 CPU 使用率上升。但是他們沒(méi)有必然聯(lián)系,CPU 密集型計(jì)算任務(wù)較多一般系統(tǒng)平均負(fù)載會(huì)上升,但是如果 IO 密集型任務(wù)較多也會(huì)導(dǎo)致系統(tǒng)平均負(fù)載升高但是此時(shí)的 CPU 使用率不一定高,可能很低因?yàn)楹芏噙M(jìn)程都處于不可中斷狀態(tài),等待 CPU 調(diào)度也會(huì)升高系統(tǒng)平均負(fù)載。

        所以假如我們系統(tǒng)平均負(fù)載很高,但是 CPU 使用率不是很高,則需要考慮是否系統(tǒng)遇到了 IO 瓶頸,應(yīng)該優(yōu)化 IO 讀寫速度。

        所以系統(tǒng)是否遇到 CPU 瓶頸需要結(jié)合 CPU 使用率,系統(tǒng)瓶頸負(fù)載一起查看(當(dāng)然還有其他指標(biāo)需要對(duì)比查看,下面繼續(xù)講解)

        案例問(wèn)題排查

        stress是一個(gè)施加系統(tǒng)壓力和壓力測(cè)試系統(tǒng)的工具,我們可以使用stress工具壓測(cè)試 CPU,以便方便我們定位和排查 CPU 問(wèn)題。

        yum install stress // 安裝stress工具
        stress 命令使用
         // --cpu 8:8個(gè)進(jìn)程不停的執(zhí)行sqrt()計(jì)算操作 // --io 4:4個(gè)進(jìn)程不同的執(zhí)行sync()io操作(刷盤) // --vm 2:2個(gè)進(jìn)程不停的執(zhí)行malloc()內(nèi)存申請(qǐng)操作 // --vm-bytes 128M:限制1個(gè)執(zhí)行malloc的進(jìn)程申請(qǐng)內(nèi)存大小 stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 10s

        我們這里主要驗(yàn)證 CPU、IO、進(jìn)程數(shù)過(guò)多的問(wèn)題

        CPU 問(wèn)題排查

        使用stress -c 1模擬 CPU 高負(fù)載情況,然后使用如下命令觀察負(fù)載變化情況:

        uptime:使用uptime查看此時(shí)系統(tǒng)負(fù)載:

        # -d 參數(shù)表示高亮顯示變化的區(qū)域$ watch -d uptime... load average: 1.00, 0.75, 0.39

        mpstat:使用mpstat -P ALL 1則可以查看每一秒的 CPU 每一核變化信息,整體和top類似,好處是可以把每一秒(自定義)的數(shù)據(jù)輸出方便觀察數(shù)據(jù)的變化,最終輸出平均數(shù)據(jù):

        13:14:53     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle13:14:58     all   12.89    0.00    0.18    0.00    0.00    0.03    0.00    0.00    0.00   86.9113:14:58       0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.0013:14:58       1    0.40    0.00    0.20    0.00    0.00    0.20    0.00    0.00    0.00   99.20

        由以上輸出可以得出結(jié)論,當(dāng)前系統(tǒng)負(fù)載升高,并且其中 1 個(gè)核跑滿主要在執(zhí)行用戶態(tài)任務(wù),此時(shí)大多數(shù)屬于業(yè)務(wù)工作。所以此時(shí)需要查哪個(gè)進(jìn)程導(dǎo)致單核 CPU 跑滿:

        pidstat:使用pidstat -u 1則是每隔 1 秒輸出當(dāng)前系統(tǒng)進(jìn)程、CPU 數(shù)據(jù):

        13:18:00      UID       PID    %usr %system  %guest    %CPU   CPU  Command13:18:01        0         1    1.00    0.00    0.00    1.00     4  systemd13:18:01        0   3150617  100.00    0.00    0.00  100.00     0  stress...

        top:當(dāng)然最方便的還是使用top命令查看負(fù)載情況:

        top - 13:19:06 up 125 days, 20:01,  3 users,  load average: 0.99, 0.63, 0.42Tasks: 223 total,   2 running, 221 sleeping,   0 stopped,   0 zombie%Cpu(s): 14.5 us,  0.3 sy,  0.0 ni, 85.1 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 stKiB Mem : 16166056 total,  3118532 free,  9550108 used,  3497416 buff/cacheKiB Swap:        0 total,        0 free,        0 used.  6447640 avail Mem
        PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND3150617 root 20 0 10384 120 0 R 100.0 0.0 4:36.89 stress

        此時(shí)可以看到是stress占用了很高的 CPU。

        IO 問(wèn)題排查

        我們使用stress -i 1來(lái)模擬 IO 瓶頸問(wèn)題,即死循環(huán)執(zhí)行 sync 刷盤操作:uptime:使用uptime查看此時(shí)系統(tǒng)負(fù)載:

        $ watch -d uptime...,  load average: 1.06, 0.58, 0.37

        mpstat:查看此時(shí) IO 消耗,但是實(shí)際上我們發(fā)現(xiàn)這里 CPU 基本都消耗在了 sys 即系統(tǒng)消耗上。

        Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idleAverage:     all    0.33    0.00   12.64    0.13    0.00    0.00    0.00    0.00    0.00   86.90Average:       0    0.00    0.00   99.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00Average:       1    0.00    0.00    0.33    0.00    0.00    0.00    0.00    0.00    0.00   99.67

        IO 無(wú)法升高的問(wèn)題

        iowait 無(wú)法升高的問(wèn)題,是因?yàn)榘咐?stress 使用的是 sync()系統(tǒng)調(diào)用,它的作用是刷新緩沖區(qū)內(nèi)存到磁盤中。對(duì)于新安裝的虛擬機(jī),緩沖區(qū)可能比較小,無(wú)法產(chǎn)生大的 IO 壓力,這樣大部分就都是系統(tǒng)調(diào)用的消耗了。所以,你會(huì)看到只有系統(tǒng) CPU 使用率升高。解決方法是使用 stress 的下一代 stress-ng,它支持更豐富的選項(xiàng),比如stress-ng -i 1 --hdd 1 --timeout 600(--hdd 表示讀寫臨時(shí)文件)。

        Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idleAverage:     all    0.25    0.00    0.44   26.22    0.00    0.00    0.00    0.00    0.00   73.09Average:       0    0.00    0.00    1.02   98.98    0.00    0.00    0.00    0.00    0.00    0.00

        pidstat:同上(略)

        可以看出 CPU 的 IO 升高導(dǎo)致系統(tǒng)平均負(fù)載升高。我們使用pidstat查找具體是哪個(gè)進(jìn)程導(dǎo)致 IO 升高的。

        top:這里使用 top 依舊是最方面的查看綜合參數(shù),可以得出stress是導(dǎo)致 IO 升高的元兇。

        pidstat 沒(méi)有 iowait 選項(xiàng):可能是 CentOS 默認(rèn)的sysstat太老導(dǎo)致,需要升級(jí)到 11.5.5 之后的版本才可用。

        進(jìn)程數(shù)過(guò)多問(wèn)題排查

        進(jìn)程數(shù)過(guò)多這個(gè)問(wèn)題比較特殊,如果系統(tǒng)運(yùn)行了很多進(jìn)程超出了 CPU 運(yùn)行能,就會(huì)出現(xiàn)等待 CPU 的進(jìn)程。使用stress -c 24來(lái)模擬執(zhí)行 24 個(gè)進(jìn)程(我的 CPU 是 8 核)uptime:使用uptime查看此時(shí)系統(tǒng)負(fù)載:

        $ watch -d uptime...,  load average: 18.50, 7.13, 2.84

        mpstat:同上(略)

        pidstat:同上(略)

        可以觀察到此時(shí)的系統(tǒng)處理嚴(yán)重過(guò)載的狀態(tài),平均負(fù)載高達(dá) 18.50。

        top:我們還可以使用top命令查看此時(shí)Running狀態(tài)的進(jìn)程數(shù),這個(gè)數(shù)量很多就表示系統(tǒng)正在運(yùn)行、等待運(yùn)行的進(jìn)程過(guò)多。

        總結(jié)

        通過(guò)以上問(wèn)題現(xiàn)象及解決思路可以總結(jié)出:

        1. 平均負(fù)載高有可能是 CPU 密集型進(jìn)程導(dǎo)致的
        2. 平均負(fù)載高并不一定代表 CPU 使用率高,還有可能是 I/O 更繁忙了
        3. 當(dāng)發(fā)現(xiàn)負(fù)載高的時(shí)候,你可以使用 mpstat、pidstat 等工具,輔助分析負(fù)載的來(lái)源

        總結(jié)工具:mpstatpidstat、topuptime

        CPU 上下文切換

        CPU 上下文:CPU 執(zhí)行每個(gè)任務(wù)都需要知道任務(wù)從哪里加載、又從哪里開始運(yùn)行,也就是說(shuō),需要系統(tǒng)事先幫它設(shè)置好 CPU 寄存器和程序計(jì)數(shù)器(Program Counter,PC)包括 CPU 寄存器在內(nèi)都被稱為 CPU 上下文。

        CPU 上下文切換:CPU 上下文切換,就是先把前一個(gè)任務(wù)的 CPU 上下文(也就是 CPU 寄存器和程序計(jì)數(shù)器)保存起來(lái),然后加載新任務(wù)的上下文到這些寄存器和程序計(jì)數(shù)器,最后再跳轉(zhuǎn)到程序計(jì)數(shù)器所指的新位置,運(yùn)行新任務(wù)。

        CPU 上下文切換:分為進(jìn)程上下文切換、線程上下文切換以及中斷上下文切換。

        進(jìn)程上下文切換

        從用戶態(tài)切換到內(nèi)核態(tài)需要通過(guò)系統(tǒng)調(diào)用來(lái)完成,這里就會(huì)發(fā)生進(jìn)程上下文切換(特權(quán)模式切換),當(dāng)切換回用戶態(tài)同樣發(fā)生上下文切換。

        一般每次上下文切換都需要幾十納秒到數(shù)微秒的 CPU 時(shí)間,如果切換較多還是很容易導(dǎo)致 CPU 時(shí)間的浪費(fèi)在寄存器、內(nèi)核棧以及虛擬內(nèi)存等資源的保存和恢復(fù)上,這里同樣會(huì)導(dǎo)致系統(tǒng)平均負(fù)載升高。

        Linux 為每個(gè) CPU 維護(hù)一個(gè)就緒隊(duì)列,將 R 狀態(tài)進(jìn)程按照優(yōu)先級(jí)和等待 CPU 時(shí)間排序,選擇最需要的 CPU 進(jìn)程執(zhí)行。這里運(yùn)行進(jìn)程就涉及了進(jìn)程上下文切換的時(shí)機(jī):

        1. 進(jìn)程時(shí)間片耗盡、。
        2. 進(jìn)程在系統(tǒng)資源不足(內(nèi)存不足)。
        3. 進(jìn)程主動(dòng)sleep。
        4. 有優(yōu)先級(jí)更高的進(jìn)程執(zhí)行。
        5. 硬中斷發(fā)生。

        線程上下文切換

        線程和進(jìn)程:

        1. 當(dāng)進(jìn)程只有一個(gè)線程時(shí),可以認(rèn)為進(jìn)程就等于線程。
        2. 當(dāng)進(jìn)程擁有多個(gè)線程時(shí),這些線程會(huì)共享相同的虛擬內(nèi)存和全局變量等資源。這些資源在上下文切換時(shí)是不需要修改的。
        3. 線程也有自己的私有數(shù)據(jù),比如棧和寄存器等,這些在上下文切換時(shí)也是需要保存的。

        所以線程上下文切換包括了 2 種情況:

        1. 不同進(jìn)程的線程,這種情況等同于進(jìn)程切換。
        2. 通進(jìn)程的線程切換,只需要切換線程私有數(shù)據(jù)、寄存器等不共享數(shù)據(jù)。

        中斷上下文切換

        中斷處理會(huì)打斷進(jìn)程的正常調(diào)度和執(zhí)行,轉(zhuǎn)而調(diào)用中斷處理程序,響應(yīng)設(shè)備事件。而在打斷其他進(jìn)程時(shí),就需要將進(jìn)程當(dāng)前的狀態(tài)保存下來(lái),這樣在中斷結(jié)束后,進(jìn)程仍然可以從原來(lái)的狀態(tài)恢復(fù)運(yùn)行。

        對(duì)同一個(gè) CPU 來(lái)說(shuō),中斷處理比進(jìn)程擁有更高的優(yōu)先級(jí),所以中斷上下文切換并不會(huì)與進(jìn)程上下文切換同時(shí)發(fā)生。由于中斷會(huì)打斷正常進(jìn)程的調(diào)度和執(zhí)行,所以大部分中斷處理程序都短小精悍,以便盡可能快的執(zhí)行結(jié)束。

        查看系統(tǒng)上下文切換

        vmstat:工具可以查看系統(tǒng)的內(nèi)存、CPU 上下文切換以及中斷次數(shù):

        // 每隔1秒輸出$ vmstat 1procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 3  0      0 157256 3241604 5144444    0    0    20     0 26503 33960 18  7 75  0  017  0      0 159984 3241708 5144452    0    0    12     0 29560 37696 15 10 75  0  0 6  0      0 162044 3241816 5144456    0    0     8   120 30683 38861 17 10 73  0  0

        cs:則為每秒的上下文切換次數(shù)。

        in:則為每秒的中斷次數(shù)。

        r:就緒隊(duì)列長(zhǎng)度,正在運(yùn)行或等待 CPU 的進(jìn)程。

        b:不可中斷睡眠狀態(tài)的進(jìn)程數(shù),例如正在和硬件交互。

        pidstat:使用pidstat -w選項(xiàng)查看具體進(jìn)程的上下文切換次數(shù):

        $ pidstat -w -p 3217281 110:19:13      UID       PID   cswch/s nvcswch/s  Command10:19:14        0   3217281      0.00     18.00  stress10:19:15        0   3217281      0.00     18.00  stress10:19:16        0   3217281      0.00     28.71  stress

        其中cswch/snvcswch/s表示自愿上下文切換和非自愿上下文切換。

        自愿上下文切換:是指進(jìn)程無(wú)法獲取所需資源,導(dǎo)致的上下文切換。比如說(shuō), I/O、內(nèi)存等系統(tǒng)資源不足時(shí),就會(huì)發(fā)生自愿上下文切換。

        非自愿上下文切換:則是指進(jìn)程由于時(shí)間片已到等原因,被系統(tǒng)強(qiáng)制調(diào)度,進(jìn)而發(fā)生的上下文切換。比如說(shuō),大量進(jìn)程都在爭(zhēng)搶 CPU 時(shí),就容易發(fā)生非自愿上下文切換

        案例問(wèn)題排查

        這里我們使用sysbench工具模擬上下文切換問(wèn)題。

        先使用vmstat 1查看當(dāng)前上下文切換信息:

        $ vmstat 1procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 2  0      0 514540 3364828 5323356    0    0    10    16    0    0  4  1 95  0  0 1  0      0 514316 3364932 5323408    0    0     8     0 27900 34809 17 10 73  0  0 1  0      0 507036 3365008 5323500    0    0     8     0 23750 30058 19  9 72  0  0

        然后使用sysbench --threads=64 --max-time=300 threads run模擬 64 個(gè)線程執(zhí)行任務(wù),此時(shí)我們?cè)俅?code style="overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;font-family: "Microsoft YaHei";">vmstat 1查看上下文切換信息:

        $ vmstat 1procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 2  0      0 318792 3385728 5474272    0    0    10    16    0    0  4  1 95  0  0 1  0      0 307492 3385756 5474316    0    0     8     0 15710 20569 20  8 72  0  0 1  0      0 330032 3385824 5474376    0    0     8    16 21573 26844 19  9 72  0  0 2  0      0 321264 3385876 5474396    0    0    12     0 21218 26100 20  7 73  0  0 6  0      0 320172 3385932 5474440    0    0    12     0 19363 23969 19  8 73  0  014  0      0 323488 3385980 5474828    0    0    64   788 111647 3745536 24 61 15  0  014  0      0 323576 3386028 5474856    0    0     8     0 118383 4317546 25 64 11  0  016  0      0 315560 3386100 5475056    0    0     8    16 115253 4553099 22 68  9  0  0

        我們可以明顯的觀察到:

        1. 當(dāng)前 cs、in 此時(shí)劇增。
        2. sy+us 的 CPU 占用超過(guò) 90%。
        3. r 就緒隊(duì)列長(zhǎng)度達(dá)到 16 個(gè)超過(guò)了 CPU 核心數(shù) 8 個(gè)。
        分析 cs 上下文切換問(wèn)題

        我們使用pidstat查看當(dāng)前 CPU 信息和具體的進(jìn)程上下文切換信息:

        // -w表示查看進(jìn)程切換信息,-u查看CPU信息,-t查看線程切換信息$ pidstat -w -u -t 1
        10:35:01 UID PID %usr %system %guest %CPU CPU Command10:35:02 0 3383478 67.33 100.00 0.00 100.00 1 sysbench
        10:35:01 UID PID cswch/s nvcswch/s Command10:45:39 0 3509357 - 1.00 0.00 kworker/2:210:45:39 0 - 3509357 1.00 0.00 |__kworker/2:210:45:39 0 - 3509702 38478.00 45587.00 |__sysbench10:45:39 0 - 3509703 39913.00 41565.00 |__sysbench

        所以我們可以看到大量的sysbench線程存在很多的上下文切換。

        分析 in 中斷問(wèn)題

        我們可以查看系統(tǒng)的watch -d cat /proc/softirqs以及watch -d cat /proc/interrupts來(lái)查看系統(tǒng)的軟中斷和硬中斷(內(nèi)核中斷)。我們這里主要觀察/proc/interrupts即可。

        $ watch -d cat /proc/interruptsRES:  900997016  912023527  904378994  902594579  899800739  897500263  895024925  895452133   Rescheduling interrupts

        這里明顯看出重調(diào)度中斷(RES)增多,這個(gè)中斷表示喚醒空閑狀態(tài) CPU 來(lái)調(diào)度新任務(wù)執(zhí)行,

        總結(jié)

        1. 自愿上下文切換變多了,說(shuō)明進(jìn)程都在等待資源,有可能發(fā)生了 I/O 等其他問(wèn)題。
        2. 非自愿上下文切換變多了,說(shuō)明進(jìn)程都在被強(qiáng)制調(diào)度,也就是都在爭(zhēng)搶 CPU,說(shuō)明 CPU 的確成了瓶頸。
        3. 中斷次數(shù)變多了,說(shuō)明 CPU 被中斷處理程序占用,還需要通過(guò)查看/proc/interrupts文件來(lái)分析具體的中斷類型。

        CPU 使用率

        除了系統(tǒng)負(fù)載、上下文切換信息,最直觀的 CPU 問(wèn)題指標(biāo)就是 CPU 使用率信息。Linux 通過(guò)/proc虛擬文件系統(tǒng)向用戶控件提供系統(tǒng)內(nèi)部狀態(tài)信息,其中/proc/stat則是 CPU 和任務(wù)信息統(tǒng)計(jì)。

        $ cat /proc/stat | grep cpucpu  6392076667 1160 3371352191 52468445328 3266914 37086 36028236 20721765 0 0cpu0 889532957 175 493755012 6424323330 2180394 37079 17095455 3852990 0 0...

        這里每一列的含義如下:

        1. user(通??s寫為 us),代表用戶態(tài) CPU 時(shí)間。注意,它不包括下面的 nice 時(shí)間,但包括了 guest 時(shí)間。
        2. nice(通??s寫為 ni),代表低優(yōu)先級(jí)用戶態(tài) CPU 時(shí)間,也就是進(jìn)程的 nice 值被調(diào)整為 1-19 之間時(shí)的 CPU 時(shí)間。這里注意,nice 可取值范圍是 -20 到 19,數(shù)值越大,優(yōu)先級(jí)反而越低。
        3. system(通??s寫為 sys),代表內(nèi)核態(tài) CPU 時(shí)間。
        4. idle(通??s寫為 id),代表空閑時(shí)間。注意,它不包括等待 I/O 的時(shí)間(iowait)。
        5. iowait(通常縮寫為 wa),代表等待 I/O 的 CPU 時(shí)間。
        6. irq(通??s寫為 hi),代表處理硬中斷的 CPU 時(shí)間。
        7. softirq(通??s寫為 si),代表處理軟中斷的 CPU 時(shí)間。
        8. steal(通??s寫為 st),代表當(dāng)系統(tǒng)運(yùn)行在虛擬機(jī)中的時(shí)候,被其他虛擬機(jī)占用的 CPU 時(shí)間。
        9. guest(通??s寫為 guest),代表通過(guò)虛擬化運(yùn)行其他操作系統(tǒng)的時(shí)間,也就是運(yùn)行虛擬機(jī)的 CPU 時(shí)間。
        10. guest_nice(通常縮寫為 gnice),代表以低優(yōu)先級(jí)運(yùn)行虛擬機(jī)的時(shí)間。

        這里我們可以使用top、ps、pidstat等工具方便的查詢這些數(shù)據(jù),可以很方便的看到 CPU 使用率很高的進(jìn)程,這里我們可以通過(guò)這些工具初步定為,但是具體的問(wèn)題原因還需要其他方法繼續(xù)查找。

        這里我們可以使用perf top方便查看熱點(diǎn)數(shù)據(jù),也可以使用perf record可以將當(dāng)前數(shù)據(jù)保存起來(lái)方便后續(xù)使用perf report查看。

        CPU 使用率問(wèn)題排查

        這里總結(jié)一下 CPU 使用率問(wèn)題及排查思路:

        1. 用戶 CPU 和 Nice CPU 高,說(shuō)明用戶態(tài)進(jìn)程占用了較多的 CPU,所以應(yīng)該著重排查進(jìn)程的性能問(wèn)題。
        2. 系統(tǒng) CPU 高,說(shuō)明內(nèi)核態(tài)占用了較多的 CPU,所以應(yīng)該著重排查內(nèi)核線程或者系統(tǒng)調(diào)用的性能問(wèn)題。
        3. I/O 等待 CPU 高,說(shuō)明等待 I/O 的時(shí)間比較長(zhǎng),所以應(yīng)該著重排查系統(tǒng)存儲(chǔ)是不是出現(xiàn)了 I/O 問(wèn)題。
        4. 軟中斷和硬中斷高,說(shuō)明軟中斷或硬中斷的處理程序占用了較多的 CPU,所以應(yīng)該著重排查內(nèi)核中的中斷服務(wù)程序。

        CPU 問(wèn)題排查套路

        CPU 使用率

        CPU 使用率主要包含以下幾個(gè)方面:

        1. 用戶 CPU 使用率,包括用戶態(tài) CPU 使用率(user)和低優(yōu)先級(jí)用戶態(tài) CPU 使用率(nice),表示 CPU 在用戶態(tài)運(yùn)行的時(shí)間百分比。用戶 CPU 使用率高,通常說(shuō)明有應(yīng)用程序比較繁忙。
        2. 系統(tǒng) CPU 使用率,表示 CPU 在內(nèi)核態(tài)運(yùn)行的時(shí)間百分比(不包括中斷)。系統(tǒng) CPU 使用率高,說(shuō)明內(nèi)核比較繁忙。
        3. 等待 I/O 的 CPU 使用率,通常也稱為 iowait,表示等待 I/O 的時(shí)間百分比。iowait 高,通常說(shuō)明系統(tǒng)與硬件設(shè)備的 I/O 交互時(shí)間比較長(zhǎng)。
        4. 軟中斷和硬中斷的 CPU 使用率,分別表示內(nèi)核調(diào)用軟中斷處理程序、硬中斷處理程序的時(shí)間百分比。它們的使用率高,通常說(shuō)明系統(tǒng)發(fā)生了大量的中斷。
        5. 除在虛擬化環(huán)境中會(huì)用到的竊取 CPU 使用率(steal)和客戶 CPU 使用率(guest),分別表示被其他虛擬機(jī)占用的 CPU 時(shí)間百分比,和運(yùn)行客戶虛擬機(jī)的 CPU 時(shí)間百分比。

        平均負(fù)載

        反應(yīng)了系統(tǒng)的整體負(fù)載情況,可以查看過(guò)去 1 分鐘、過(guò)去 5 分鐘和過(guò)去 15 分鐘的平均負(fù)載。

        上下文切換

        上下文切換主要關(guān)注 2 項(xiàng)指標(biāo):

        1. 無(wú)法獲取資源而導(dǎo)致的自愿上下文切換。
        2. 被系統(tǒng)強(qiáng)制調(diào)度導(dǎo)致的非自愿上下文切換。

        CPU 緩存命中率

        CPU 的訪問(wèn)速度遠(yuǎn)大于內(nèi)存訪問(wèn),這樣在 CPU 訪問(wèn)內(nèi)存時(shí)不可避免的要等待內(nèi)存響應(yīng)。為了協(xié)調(diào) 2 者的速度差距出現(xiàn)了 CPU 緩存(多級(jí)緩存)。如果 CPU 緩存命中率越高則性能會(huì)更好,我們可以使用以下工具查看 CPU 緩存命中率,工具地址、項(xiàng)目地址 perf-tools

        # ./cachestat -tCounting cache functions... Output every 1 seconds.TIME         HITS   MISSES  DIRTIES    RATIO   BUFFERS_MB   CACHE_MB08:28:57      415        0        0   100.0%            1        19108:28:58      411        0        0   100.0%            1        19108:28:59      362       97        0    78.9%            0          808:29:00      411        0        0   100.0%            0          908:29:01      775    20489        0     3.6%            0         8908:29:02      411        0        0   100.0%            0         8908:29:03     6069        0        0   100.0%            0         8908:29:04    15249        0        0   100.0%            0         8908:29:05      411        0        0   100.0%            0         8908:29:06      411        0        0   100.0%            0         8908:29:07      411        0        3   100.0%            0         89[...]

        總結(jié)

        通過(guò)性能指標(biāo)查工具(CPU 相關(guān))

        性能指標(biāo)工具說(shuō)明
        平均負(fù)載uptime
        top
        uptime 簡(jiǎn)單展示最近一段時(shí)間的平均負(fù)載
        top 展示更多指標(biāo)
        CPU 使用率vmstat
        mpstat
        top
        sar
        /proc/stat
        top、vmstat、mpstat 只可以動(dòng)態(tài)查看當(dāng)前,而 sar 可以查看歷史
        /proc/stat 是其他性能工具的數(shù)據(jù)來(lái)源
        進(jìn)程 CPU 使用率top
        pidstat
        ps
        htop
        atop
        top、ps 可以以排序方式展示進(jìn)程 CPU、pidstat 不可排序展示
        htop、atop 則以不同顏色展示各類數(shù)據(jù)更直觀
        系統(tǒng)上下文切換vmstat展示上下文切換此時(shí)、運(yùn)行狀態(tài)、不可中斷狀態(tài)進(jìn)程數(shù)量
        進(jìn)程上下文切換pidstat展示項(xiàng)很多,包括進(jìn)程上下文切換信息
        軟中斷top
        /proc/softirqs
        mpstat
        top 可查看軟中斷 CPU 使用率
        /proc/softirqs 和 mpstat 則可以查看每個(gè) CPU 上的累計(jì)信息
        硬中斷vmstat
        /proc/interrupts
        vmstat 查看總中斷次數(shù)信息
        /proc/interrupts 查看各種中斷在每個(gè) CPU 核心上的累計(jì)信息
        網(wǎng)絡(luò)dstat
        sar
        tcpdump
        dstat、sar 較詳細(xì)的展示出總的網(wǎng)絡(luò)收發(fā)情況
        tcpdump 提供動(dòng)態(tài)抓取數(shù)據(jù)包的能力
        IOdstat、sar2 者都提供了詳細(xì)的 IO 整體情況
        CPU 信息/proc/cpuinfo
        lscpu
        都可以查看 CPU 信息
        系統(tǒng)分析perf
        execsnoop
        perf 分析各種內(nèi)核函數(shù)調(diào)用、熱點(diǎn)函數(shù)信息
        execsnoop 監(jiān)控短時(shí)進(jìn)程

        根據(jù)工具查性能指標(biāo)(CPU 相關(guān))

        性能工具CPU 性能指標(biāo)
        uptime5、10、15 分鐘內(nèi)的平均負(fù)載展示
        top平均負(fù)載、運(yùn)行隊(duì)列、CPU 各項(xiàng)使用率、進(jìn)程狀態(tài)和 CPU 使用率
        htoptop 增強(qiáng)版,以不同顏色區(qū)分不同類型進(jìn)程,展示更直觀
        atopCPU、內(nèi)存、磁盤、網(wǎng)絡(luò)資源全訪問(wèn)監(jiān)控,十分齊全
        vmstat系統(tǒng)整體 CPU 使用率、上下文切換次數(shù)、中斷次數(shù),還包括處于運(yùn)行(r)和不可中斷狀態(tài)(b)的進(jìn)程數(shù)量
        pidstat進(jìn)程、線程(-t)的每個(gè) CPU 占用信息,中斷上下文切換次數(shù)
        /proc/softirqs展示每個(gè) CPU 上的軟中斷類型及次數(shù)
        /proc/inerrupts展示每個(gè) CPU 上的硬中斷類型及次數(shù)
        ps每個(gè)進(jìn)程的狀態(tài)和 CPU 使用率
        pstree進(jìn)程的父子關(guān)系展示
        dstat系統(tǒng)整體 CPU 使用率(以及相關(guān) IO、網(wǎng)絡(luò)信息)
        sar系統(tǒng)整體 CPU 使用率,以及使用率歷史信息
        strace跟蹤進(jìn)程的系統(tǒng)調(diào)用
        perfCPU 性能事件分析,例如:函數(shù)調(diào)用鏈、CPU 緩存命中率、CPU 調(diào)度等
        execsnoop短時(shí)進(jìn)程分析

        CPU 問(wèn)題排查方向

        有了以上性能工具,在實(shí)際遇到問(wèn)題時(shí)我們并不可能全部性能工具跑一遍,這樣效率也太低了,所以這里可以先運(yùn)行幾個(gè)常用的工具 top、vmstat、pidstat 分析系統(tǒng)大概的運(yùn)行情況然后在具體定位原因。

        top 系統(tǒng)CPU => vmstat 上下文切換次數(shù) => pidstat 非自愿上下文切換次數(shù) => 各類進(jìn)程分析工具(perf strace ps execsnoop pstack)
        top 用戶CPU => pidstat 用戶CPU => 一般是CPU計(jì)算型任務(wù)
        top 僵尸進(jìn)程 => 各類進(jìn)程分析工具(perf strace ps execsnoop pstack)
        top 平均負(fù)載 => vmstat 運(yùn)行狀態(tài)進(jìn)程數(shù) => pidstat 用戶CPU => 各類進(jìn)程分析工具(perf strace ps execsnoop pstack)
        top 等待IO CPU => vmstat 不可中斷狀態(tài)進(jìn)程數(shù) => IO分析工具(dstat、sar -d)
        top 硬中斷 => vmstat 中斷次數(shù) => 查看具體中斷類型(/proc/interrupts)
        top 軟中斷 => 查看具體中斷類型(/proc/softirqs) => 網(wǎng)絡(luò)分析工具(sar -n、tcpdump) 或者 SCHED(pidstat 非自愿上下文切換)

        CPU 問(wèn)題優(yōu)化方向

        性能優(yōu)化往往是多方面的,CPU、內(nèi)存、網(wǎng)絡(luò)等都是有關(guān)聯(lián)的,這里暫且給出 CPU 優(yōu)化的思路,以供參考。

        程序優(yōu)化
        1. 基本優(yōu)化:程序邏輯的優(yōu)化比如減少循環(huán)次數(shù)、減少內(nèi)存分配,減少遞歸等等。
        2. 編譯器優(yōu)化:開啟編譯器優(yōu)化選項(xiàng)例如gcc -O2對(duì)程序代碼優(yōu)化。
        3. 算法優(yōu)化:降低蘇研發(fā)復(fù)雜度,例如使用nlogn的排序算法,使用logn的查找算法等。
        4. 異步處理:例如把輪詢改為通知方式
        5. 多線程代替多進(jìn)程:某些場(chǎng)景下多線程可以代替多進(jìn)程,因?yàn)樯舷挛那袚Q成本較低
        6. 緩存:包括多級(jí)緩存的使用(略)加快數(shù)據(jù)訪問(wèn)
        系統(tǒng)優(yōu)化
        1. CPU 綁定:綁定到一個(gè)或多個(gè) CPU 上,可以提高 CPU 緩存命中率,減少跨 CPU 調(diào)度帶來(lái)的上下文切換問(wèn)題
        2. CPU 獨(dú)占:跟 CPU 綁定類似,進(jìn)一步將 CPU 分組,并通過(guò) CPU 親和性機(jī)制為其分配進(jìn)程。
        3. 優(yōu)先級(jí)調(diào)整:使用 nice 調(diào)整進(jìn)程的優(yōu)先級(jí),適當(dāng)降低非核心應(yīng)用的優(yōu)先級(jí),增高核心應(yīng)用的優(yōu)先級(jí),可以確保核心應(yīng)用得到優(yōu)先處理。
        4. 為進(jìn)程設(shè)置資源限制:使用 Linux cgroups 來(lái)設(shè)置進(jìn)程的 CPU 使用上限,可以防止由于某個(gè)應(yīng)用自身的問(wèn)題,而耗盡系統(tǒng)資源。
        5. NUMA 優(yōu)化:支持 NUMA 的處理器會(huì)被劃分為多個(gè) Node,每個(gè) Node 有本地的內(nèi)存空間,這樣 CPU 可以直接訪問(wèn)本地空間內(nèi)存。
        6. 中斷負(fù)載均衡:無(wú)論是軟中斷還是硬中斷,它們的中斷處理程序都可能會(huì)耗費(fèi)大量的 CPU。開啟 irqbalance 服務(wù)或者配置 smp_affinity,就可以把中斷處理過(guò)程自動(dòng)負(fù)載均衡到多個(gè) CPU 上。

        參考

        極客時(shí)間:Linux 性能優(yōu)化實(shí)戰(zhàn)

        瀏覽 48
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            女人18片毛片90分钟免费明星 | 懂色av浪潮av色欲av熟妇 | 啊啊啊啊啊好大好深 | 91探花足浴店少妇在线 | 日本理论片午伦夜理片2021主演 | 超碰国产在线 | 一级a做一级a做片性视频爱小说 | 人人操人人干人人射 | 激情婷婷久久 | 我穿开裆裤的老公突然跟我打招呼 |