偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Linux CPU 優(yōu)化:揪出拖慢性能的“元兇”

系統(tǒng) Linux
正因如此,深入了解 CPU 性能問(wèn)題,掌握優(yōu)化技巧,對(duì) Linux 系統(tǒng)的穩(wěn)定高效運(yùn)行至關(guān)重要。接下來(lái),就讓我們一同開(kāi)啟探索 CPU 性能優(yōu)化之旅,揪出那些拖慢系統(tǒng)性能的 “元兇” 。

在Linux系統(tǒng)的廣袤世界里,無(wú)論是運(yùn)行關(guān)鍵業(yè)務(wù)的服務(wù)器,還是開(kāi)發(fā)者手中的開(kāi)發(fā)環(huán)境,CPU 就如同跳動(dòng)的心臟,其性能直接決定了系統(tǒng)的生命力。當(dāng) CPU 性能出現(xiàn)問(wèn)題,就像心臟供血不足,會(huì)引發(fā)一系列連鎖反應(yīng),其中最明顯的就是服務(wù)卡頓和響應(yīng)遲緩。

想象一下,你運(yùn)營(yíng)著一個(gè)基于 Linux 系統(tǒng)的電商網(wǎng)站,在促銷活動(dòng)期間,大量用戶涌入。此時(shí),如果 CPU 性能不佳,用戶點(diǎn)擊商品詳情可能要等待數(shù)秒才能加載出來(lái),下單操作更是遲遲沒(méi)有響應(yīng)。這不僅嚴(yán)重影響用戶體驗(yàn),還可能導(dǎo)致大量訂單流失,給業(yè)務(wù)帶來(lái)巨大損失。又比如,在數(shù)據(jù)分析場(chǎng)景中,Linux 服務(wù)器需要處理海量數(shù)據(jù),如果 CPU 性能瓶頸凸顯,原本幾小時(shí)能完成的數(shù)據(jù)分析任務(wù),可能會(huì)延長(zhǎng)數(shù)倍時(shí)間,讓寶貴的商業(yè)決策時(shí)機(jī)白白溜走。

正因如此,深入了解 CPU 性能問(wèn)題,掌握優(yōu)化技巧,對(duì) Linux 系統(tǒng)的穩(wěn)定高效運(yùn)行至關(guān)重要。接下來(lái),就讓我們一同開(kāi)啟探索 CPU 性能優(yōu)化之旅,揪出那些拖慢系統(tǒng)性能的 “元兇” 。

Part1.認(rèn)識(shí)CPU性能指標(biāo)

在深入排查 CPU 性能問(wèn)題前,我們先來(lái)認(rèn)識(shí)幾個(gè)關(guān)鍵的 CPU 性能指標(biāo),它們?nèi)缤?CPU 的 “健康密碼”,能幫助我們準(zhǔn)確判斷 CPU 的工作狀態(tài) 。

1.1平均負(fù)載(Load Average)

平均負(fù)載是指單位時(shí)間內(nèi),系統(tǒng)處于可運(yùn)行狀態(tài)和不可中斷狀態(tài)的平均進(jìn)程數(shù) ,也就是平均活躍進(jìn)程數(shù)。簡(jiǎn)單來(lái)說(shuō),它反映了系統(tǒng)的繁忙程度??蛇\(yùn)行狀態(tài)的進(jìn)程,是指正在使用 CPU 或者正在等待 CPU 的進(jìn)程;不可中斷狀態(tài)的進(jìn)程則是正處于內(nèi)核態(tài)關(guān)鍵流程中的進(jìn)程,并且這些流程是不可打斷的,最常見(jiàn)的是等待硬件設(shè)備的 I/O 響應(yīng)。

我們可以使用 uptime 命令或 top 命令來(lái)查看系統(tǒng)的平均負(fù)載。比如,執(zhí)行 uptime 命令后,得到的結(jié)果 “14:21:38 up 1 day, 1:22, 2 users, load average: 0.58, 0.65, 0.70”,其中最后三個(gè)數(shù)字 0.58、0.65、0.70 分別表示過(guò)去 1 分鐘、5 分鐘、15 分鐘的平均負(fù)載。

平均負(fù)載與 CPU 核心數(shù)密切相關(guān)。對(duì)于一個(gè)單核 CPU 系統(tǒng)來(lái)說(shuō),如果平均負(fù)載為 1,意味著 CPU 剛好被完全占用;如果平均負(fù)載大于 1,則表示有進(jìn)程在等待 CPU 資源,系統(tǒng)出現(xiàn)了過(guò)載。而在一個(gè) 4 核 CPU 系統(tǒng)中,當(dāng)平均負(fù)載為 4 時(shí),CPU 才被完全占用;若平均負(fù)載為 2,說(shuō)明 CPU 還有 50% 的空閑。一般認(rèn)為,當(dāng)平均負(fù)載高于 CPU 數(shù)量 70% 的時(shí)候,就需要關(guān)注并分析負(fù)載高的問(wèn)題了 。例如,在一個(gè)擁有 2 個(gè) CPU 核心的服務(wù)器上,如果 1 分鐘平均負(fù)載長(zhǎng)期高于 1.4,就可能會(huì)出現(xiàn)性能問(wèn)題,需要進(jìn)一步排查原因。

1.2CPU 使用率

CPU 使用率,簡(jiǎn)單來(lái)說(shuō),就是在一段時(shí)間內(nèi),CPU 被占用的時(shí)間占總時(shí)間的比例,是一個(gè)百分比數(shù)值。它就像衡量 CPU 工作強(qiáng)度的 “體溫計(jì)”,直觀地反映了 CPU 在單位時(shí)間內(nèi)有多 “忙” 。

其計(jì)算方式并不復(fù)雜。對(duì)于單核 CPU 而言,在某一時(shí)間段內(nèi),若 CPU 執(zhí)行程序指令的時(shí)間為 t1,總時(shí)間為 T,那么該時(shí)間段內(nèi)的 CPU 使用率 = (t1 / T)× 100% 。例如,在 1 秒鐘內(nèi),CPU 有 0.5 秒在執(zhí)行程序指令,那么這 1 秒內(nèi)的 CPU 使用率就是 50%。而對(duì)于多核 CPU,計(jì)算方式則是將每個(gè)核心在單位時(shí)間內(nèi)的使用率相加,再除以核心數(shù)。假設(shè)一個(gè)四核 CPU,每個(gè)核心在 1 秒內(nèi)分別被占用 0.3 秒、0.4 秒、0.2 秒和 0.1 秒,那么總的 CPU 使用率就是(0.3 + 0.4 + 0.2 + 0.1)÷ 4 × 100% = 25% 。

當(dāng) CPU 使用率較高時(shí),如達(dá)到 80% - 90% 及以上,就意味著 CPU 正在承擔(dān)大量的計(jì)算任務(wù),計(jì)算機(jī)的響應(yīng)速度可能會(huì)變慢。以運(yùn)行大型 3D 游戲?yàn)槔?,游戲運(yùn)行時(shí),CPU 需要處理復(fù)雜的圖形算法、物理模擬以及大量的游戲邏輯,這使得 CPU 的使用率急劇上升。若此時(shí) CPU 性能不足,就會(huì)導(dǎo)致游戲畫面卡頓、幀率不穩(wěn)定等問(wèn)題。相反,當(dāng) CPU 使用率較低,如在待機(jī)或者只運(yùn)行一些簡(jiǎn)單的文本編輯軟件時(shí),CPU 使用率可能只有 10% - 20% 左右,計(jì)算機(jī)能夠快速響應(yīng)用戶的其他操作指令。

1.3上下文切換

在多任務(wù)處理的環(huán)境中,Linux 系統(tǒng)看似能夠同時(shí)運(yùn)行多個(gè)任務(wù),但實(shí)際上,在同一時(shí)刻,CPU 只能執(zhí)行一個(gè)任務(wù)。為了實(shí)現(xiàn)多任務(wù)并發(fā)執(zhí)行的效果,操作系統(tǒng)引入了上下文切換機(jī)制,這就好比一場(chǎng)接力賽跑中的 “接力棒交接” 。

上下文切換,是指操作系統(tǒng)保存當(dāng)前正在執(zhí)行的任務(wù)(可以是進(jìn)程或線程)的狀態(tài)(即上下文),并加載另一個(gè)任務(wù)的狀態(tài),使得 CPU 能夠從一個(gè)任務(wù)快速切換到另一個(gè)任務(wù)執(zhí)行。這里的上下文,既包括虛擬內(nèi)存、棧、全局變量等用戶態(tài)的資源,也包括內(nèi)核堆棧、寄存器等內(nèi)核態(tài)的資源 。

在 Linux 系統(tǒng)中,進(jìn)程有多種狀態(tài),不同狀態(tài)與 CPU 的關(guān)系也各不相同:

  • 運(yùn)行態(tài)(Running):表示進(jìn)程正在被 CPU 執(zhí)行,或者在運(yùn)行隊(duì)列中等待被調(diào)度執(zhí)行。處于運(yùn)行態(tài)的進(jìn)程直接占用 CPU 資源,是 CPU 忙碌的直接原因。例如,當(dāng)我們啟動(dòng)一個(gè)計(jì)算密集型的程序時(shí),該程序的進(jìn)程會(huì)處于運(yùn)行態(tài),大量占用 CPU 時(shí)間進(jìn)行計(jì)算。
  • 可中斷睡眠態(tài)(Interruptible Sleep):進(jìn)程正在等待某一事件的發(fā)生,例如等待 I/O 操作完成、等待信號(hào)等。此時(shí)進(jìn)程處于睡眠狀態(tài),但可以通過(guò)信號(hào)喚醒。處于這種狀態(tài)的進(jìn)程不會(huì)占用 CPU 資源,直到被喚醒進(jìn)入就緒態(tài),才有可能被 CPU 調(diào)度執(zhí)行。比如,一個(gè)進(jìn)程發(fā)起了磁盤讀取操作,在等待磁盤返回?cái)?shù)據(jù)的過(guò)程中,它就處于可中斷睡眠態(tài)。
  • 不可中斷睡眠態(tài)(Uninterruptible Sleep):進(jìn)程等待某種無(wú)法通過(guò)信號(hào)喚醒的資源,通常是在等待硬件操作完成,如等待磁盤 I/O、等待網(wǎng)絡(luò)傳輸完成等。此時(shí)進(jìn)程不會(huì)響應(yīng)任何信號(hào),直到所等待的事件發(fā)生。不可中斷睡眠態(tài)的進(jìn)程雖然不占用 CPU 執(zhí)行時(shí)間,但會(huì)使系統(tǒng)的平均負(fù)載增加,因?yàn)樗幱诓豢芍袛嗟年P(guān)鍵流程中。例如,當(dāng)進(jìn)程向磁盤寫入大量數(shù)據(jù)時(shí),為了保證數(shù)據(jù)一致性,在寫入完成前,進(jìn)程會(huì)處于不可中斷睡眠態(tài)。
  • 暫停態(tài)(Stopped):進(jìn)程被暫停運(yùn)行,通常是接收到 SIGSTOP 信號(hào)導(dǎo)致。進(jìn)程停止運(yùn)行但沒(méi)有終止,所有的上下文信息都會(huì)被保留。暫停態(tài)的進(jìn)程不占用 CPU 資源,直到接收到 SIGCONT 信號(hào)恢復(fù)執(zhí)行并進(jìn)入就緒態(tài)。比如,我們?cè)谡{(diào)試程序時(shí),可以使用調(diào)試工具將進(jìn)程暫停在某個(gè)斷點(diǎn)處,此時(shí)進(jìn)程就處于暫停態(tài)。
  • 僵尸態(tài)(Zombie):進(jìn)程已完成執(zhí)行,但其父進(jìn)程尚未通過(guò) wait () 或 waitpid () 系統(tǒng)調(diào)用獲取其退出狀態(tài)并清理資源,因此進(jìn)程仍然保留著一個(gè)條目以供父進(jìn)程讀取其退出狀態(tài)。僵尸態(tài)進(jìn)程不會(huì)消耗任何 CPU 資源,但其進(jìn)程表項(xiàng)仍占用系統(tǒng)資源,長(zhǎng)時(shí)間存在可能會(huì)導(dǎo)致系統(tǒng)資源耗盡。例如,一個(gè)父進(jìn)程創(chuàng)建了多個(gè)子進(jìn)程,卻沒(méi)有正確處理子進(jìn)程的退出,就可能產(chǎn)生僵尸進(jìn)程。

圖片圖片

在多任務(wù)處理中,上下文切換發(fā)揮著至關(guān)重要的作用。它使得多個(gè)任務(wù)能夠公平、高效地共享CPU資源,從而提高系統(tǒng)的吞吐量和響應(yīng)時(shí)間。例如,當(dāng)你在電腦上同時(shí)打開(kāi)瀏覽器瀏覽網(wǎng)頁(yè)、播放音樂(lè)以及運(yùn)行文檔編輯軟件時(shí),操作系統(tǒng)通過(guò)上下文切換,在這些任務(wù)之間快速切換CPU的執(zhí)行權(quán),讓你感覺(jué)這些任務(wù)在同時(shí)進(jìn)行 。

然而,頻繁的上下文切換也會(huì)對(duì)CPU性能產(chǎn)生負(fù)面影響。這是因?yàn)槊看紊舷挛那袚Q都需要保存當(dāng)前任務(wù)的上下文信息,并加載新任務(wù)的上下文信息,這個(gè)過(guò)程涉及到 CPU 寄存器的讀寫、內(nèi)存訪問(wèn)等操作,會(huì)消耗一定的時(shí)間和CPU資源。過(guò)多的上下文切換,會(huì)占用CPU過(guò)多時(shí)間,縮短真正運(yùn)行時(shí)間,導(dǎo)致系統(tǒng)整體性能大幅下降。假設(shè)一個(gè)系統(tǒng)頻繁進(jìn)行上下文切換,CPU將大量時(shí)間耗費(fèi)在寄存器、內(nèi)核棧以及虛擬內(nèi)存等資源的保存和恢復(fù)上,真正用于執(zhí)行任務(wù)的時(shí)間就會(huì)減少,從而使得系統(tǒng)的運(yùn)行速度變慢,響應(yīng)延遲增加 。

那么,哪些因素可能導(dǎo)致上下文切換過(guò)多呢?系統(tǒng)中同時(shí)存在過(guò)多的進(jìn)程或線程,是一個(gè)常見(jiàn)的原因。當(dāng)進(jìn)程或線程數(shù)量超出 CPU 的處理能力時(shí),操作系統(tǒng)就需要頻繁地在它們之間進(jìn)行切換,以滿足每個(gè)任務(wù)的執(zhí)行需求。低優(yōu)先級(jí)進(jìn)程的競(jìng)爭(zhēng)也可能導(dǎo)致頻繁的上下文切換。如果多個(gè)低優(yōu)先級(jí)進(jìn)程在爭(zhēng)用 CPU 資源,操作系統(tǒng)為平衡負(fù)載而頻繁切換,也會(huì)增加上下文切換的次數(shù)。I/O 操作也是一個(gè)重要因素。當(dāng)進(jìn)程需要等待 I/O 操作(如磁盤讀寫或網(wǎng)絡(luò)請(qǐng)求)完成時(shí),會(huì)被掛起,操作系統(tǒng)會(huì)切換到其他進(jìn)程,若I/O操作非常頻繁,就會(huì)導(dǎo)致上下文切換頻繁發(fā)生 。

Part2.排查性能元兇

當(dāng)我們對(duì) CPU 性能指標(biāo)有了清晰認(rèn)識(shí)后,就需要借助一些強(qiáng)大的工具來(lái)排查那些導(dǎo)致 CPU 性能下降的 “元兇”。在 Linux 系統(tǒng)中,有許多實(shí)用工具,它們就像經(jīng)驗(yàn)豐富的偵探,能幫助我們從復(fù)雜的系統(tǒng)運(yùn)行狀態(tài)中找到問(wèn)題的關(guān)鍵所在 。

2.1 top與 htop:系統(tǒng)資源的實(shí)時(shí) “監(jiān)視器”

top 命令堪稱 Linux 系統(tǒng)性能監(jiān)控的 “元老”,它以簡(jiǎn)潔直觀的方式展示系統(tǒng)資源的實(shí)時(shí)使用情況,如同一位忠誠(chéng)的衛(wèi)士,時(shí)刻守護(hù)著系統(tǒng)的性能健康。在終端輸入 top,瞬間就能開(kāi)啟這場(chǎng)系統(tǒng)資源的 “實(shí)時(shí)之旅” 。

top 命令的輸出信息豐富而全面,第一行展示了系統(tǒng)的基本信息,包括當(dāng)前時(shí)間、系統(tǒng)運(yùn)行時(shí)長(zhǎng)、當(dāng)前登錄用戶數(shù)以及系統(tǒng)的平均負(fù)載(分別是過(guò)去 1 分鐘、5 分鐘和 15 分鐘的平均負(fù)載) 。這些信息就像系統(tǒng)的 “健康檔案”,為我們提供了一個(gè)宏觀的系統(tǒng)運(yùn)行概覽。平均負(fù)載是一個(gè)重要的指標(biāo),它反映了系統(tǒng)中正在運(yùn)行的進(jìn)程和等待運(yùn)行的進(jìn)程數(shù)量。如果平均負(fù)載持續(xù)高于系統(tǒng)的 CPU 核心數(shù),就像一個(gè)人同時(shí)承擔(dān)了過(guò)多的任務(wù),會(huì)導(dǎo)致系統(tǒng)運(yùn)行緩慢,響應(yīng)延遲 。

第二行呈現(xiàn)了系統(tǒng)的任務(wù)(進(jìn)程)信息,如進(jìn)程總數(shù)、正在運(yùn)行的進(jìn)程數(shù)、睡眠狀態(tài)的進(jìn)程數(shù)、停止?fàn)顟B(tài)的進(jìn)程數(shù)以及僵尸進(jìn)程數(shù) 。進(jìn)程是系統(tǒng)運(yùn)行的基本單元,了解進(jìn)程的狀態(tài)對(duì)于判斷系統(tǒng)性能至關(guān)重要。僵尸進(jìn)程是已經(jīng)結(jié)束運(yùn)行,但父進(jìn)程沒(méi)有正確回收其資源的進(jìn)程,它們雖然不占用 CPU 時(shí)間,但會(huì)占用系統(tǒng)資源,過(guò)多的僵尸進(jìn)程會(huì)導(dǎo)致系統(tǒng)資源浪費(fèi) 。

第三行則聚焦于 CPU 狀態(tài)信息,詳細(xì)列出了用戶空間占用 CPU 的百分比(us)、內(nèi)核空間占用CPU的百分比(sy)、改變過(guò)優(yōu)先級(jí)的進(jìn)程占用 CPU 的百分比(ni)、空閑CPU百分比(id)、IO 等待占用 CPU 的百分比(wa)、硬中斷占用 CPU 的百分比(hi)、軟中斷占用CPU的百分比(si)以及虛擬機(jī)偷取時(shí)間(st) 。這些指標(biāo)就像CPU的 “健康指標(biāo)”,通過(guò)它們,我們能深入了解 CPU 的工作狀態(tài)。當(dāng)us值較高時(shí),說(shuō)明用戶進(jìn)程消耗了大量的 CPU 資源,可能是某個(gè)用戶程序存在性能問(wèn)題,比如算法效率低下,需要頻繁進(jìn)行復(fù)雜的計(jì)算;sy 值高則表示系統(tǒng)內(nèi)核在 CPU 資源上的開(kāi)銷較大,這可能是由于頻繁的系統(tǒng)調(diào)用、大量的 I/O 操作或者內(nèi)核模塊的性能問(wèn)題導(dǎo)致的;wa 值高通常意味著系統(tǒng)在等待 I/O 操作完成,可能是磁盤讀寫速度過(guò)慢、網(wǎng)絡(luò)延遲過(guò)高或者 I/O 設(shè)備出現(xiàn)故障 。

除了這些基本信息,top命令還支持一些便捷的交互操作,讓我們能更靈活地監(jiān)控系統(tǒng)性能。按下大寫的“M”,結(jié)果會(huì)按照內(nèi)存占用從高到低排序,幫助我們快速找出占用內(nèi)存最多的進(jìn)程;按下大寫的“P”,則按照CPU占用率從高到低排序,讓 CPU 占用大戶無(wú)所遁形;當(dāng)服務(wù)器含有多個(gè) CPU 時(shí),按下數(shù)字 “1”,可以切換顯示各個(gè)CPU的詳細(xì)信息,讓我們能精準(zhǔn)了解每個(gè) CPU 核心的工作情況 。

如果說(shuō) top 命令是一位簡(jiǎn)潔高效的 “傳統(tǒng)偵探”,那么 htop 則是一位功能強(qiáng)大、更具交互性的 “現(xiàn)代神探”,它在 top 命令的基礎(chǔ)上進(jìn)行了全面升級(jí) 。htop 支持圖形界面的鼠標(biāo)操作,就像為我們提供了一個(gè)直觀的操作面板,讓我們能更輕松地與系統(tǒng)監(jiān)控界面交互 。它還可以橫向或縱向滾動(dòng)瀏覽進(jìn)程列表,即使面對(duì)長(zhǎng)長(zhǎng)的進(jìn)程列表和完整的命令行,也能輕松查看所有進(jìn)程信息,不放過(guò)任何一個(gè)細(xì)節(jié) 。在殺進(jìn)程時(shí),htop 無(wú)需像 top 那樣輸入繁瑣的進(jìn)程號(hào),只需輕松操作,就能快速結(jié)束目標(biāo)進(jìn)程 。

htop 的功能遠(yuǎn)不止這些。按下 F2 鍵,可以進(jìn)入設(shè)定布局界面,根據(jù)自己的需求調(diào)整監(jiān)控信息的顯示布局,讓監(jiān)控界面更符合個(gè)人使用習(xí)慣;按下 F3 鍵,能快速搜索進(jìn)程,就像在茫茫進(jìn)程海洋中找到了精準(zhǔn)定位的 “指南針”;按下 F4 鍵,可使用增量進(jìn)程過(guò)濾器,根據(jù)特定條件篩選出我們關(guān)注的進(jìn)程;按下 F5 鍵,能以樹(shù)形結(jié)構(gòu)顯示進(jìn)程關(guān)系,清晰呈現(xiàn)進(jìn)程之間的父子關(guān)系,幫助我們更好地理解系統(tǒng)的進(jìn)程架構(gòu);按下 F6 鍵,可以選擇排序方式,按照不同的指標(biāo)對(duì)進(jìn)程進(jìn)行排序,以便更方便地分析進(jìn)程的資源占用情況;按下 F7 和 F8 鍵,可以分別減少或增加進(jìn)程的 nice 值,從而調(diào)整進(jìn)程的優(yōu)先級(jí),合理分配系統(tǒng)資源;按下 F9 鍵,能對(duì)進(jìn)程傳遞信號(hào),實(shí)現(xiàn)對(duì)進(jìn)程的更多控制操作 。

在實(shí)際應(yīng)用中,top 和 htop 都有著廣泛的用途。在服務(wù)器運(yùn)維場(chǎng)景中,系統(tǒng)管理員可以通過(guò) top 實(shí)時(shí)監(jiān)控服務(wù)器的 CPU、內(nèi)存等資源使用情況,及時(shí)發(fā)現(xiàn)資源占用異常的進(jìn)程,如某個(gè)進(jìn)程突然占用大量 CPU 資源,導(dǎo)致服務(wù)器響應(yīng)變慢,管理員可以迅速通過(guò) top 或 htop 定位到該進(jìn)程,并采取相應(yīng)措施,如優(yōu)化程序代碼、調(diào)整進(jìn)程優(yōu)先級(jí)或者直接結(jié)束進(jìn)程,以保障服務(wù)器的穩(wěn)定運(yùn)行 。在開(kāi)發(fā)和測(cè)試環(huán)境中,開(kāi)發(fā)人員可以利用 htop 的強(qiáng)大交互功能,深入分析程序運(yùn)行時(shí)的資源占用情況,找出程序中的性能瓶頸,如某個(gè)函數(shù)在執(zhí)行過(guò)程中占用過(guò)多 CPU 時(shí)間,開(kāi)發(fā)人員可以針對(duì)該函數(shù)進(jìn)行優(yōu)化,提高程序的整體性能 。

2.2 vmstat 與 iostat:系統(tǒng)狀態(tài)的深度 “探測(cè)器”

vmstat 命令如同一位深入系統(tǒng)內(nèi)部的 “探測(cè)器”,能夠提供關(guān)于進(jìn)程、內(nèi)存、內(nèi)存分頁(yè)、堵塞IO、traps及CPU 活動(dòng)的詳細(xì)信息,讓我們對(duì)系統(tǒng)的運(yùn)行狀態(tài)有更全面、深入的了解 。在終端輸入vmstat,即可開(kāi)啟這個(gè)系統(tǒng)狀態(tài)的深度探測(cè)之旅 。

vmstat 命令的輸出結(jié)果分為多個(gè)部分,每個(gè)部分都蘊(yùn)含著豐富的系統(tǒng)運(yùn)行信息 。procs 部分展示了進(jìn)程相關(guān)信息,其中 r 表示運(yùn)行隊(duì)列中進(jìn)程的數(shù)量,這些進(jìn)程都處于可運(yùn)行狀態(tài),正急切地等待 CPU 的分配 。當(dāng)這個(gè)值超過(guò)了 CPU 的核心數(shù)目,就如同眾多乘客爭(zhēng)搶有限的出租車,必然會(huì)出現(xiàn) CPU 瓶頸。此時(shí),系統(tǒng)的運(yùn)行效率會(huì)大幅下降,表現(xiàn)為程序響應(yīng)遲緩、操作卡頓等。b 表示被 blocked(阻塞)的進(jìn)程數(shù),這些進(jìn)程正在等待 IO 操作完成,就像在交通擁堵的路口等待通行的車輛,它們的存在也會(huì)影響系統(tǒng)的整體性能 。

memory 部分呈現(xiàn)了內(nèi)存的使用情況,swpd 表示使用的虛擬內(nèi)存的大小,如果該值大于 0,就像一個(gè)人在小房間里放置了過(guò)多的物品,說(shuō)明機(jī)器的物理內(nèi)存可能不足。這時(shí)候,我們需要進(jìn)一步排查原因,可能是程序存在內(nèi)存泄露問(wèn)題,也可能是系統(tǒng)本身的內(nèi)存配置無(wú)法滿足當(dāng)前的業(yè)務(wù)需求。free 表示可用的物理內(nèi)存大小,它反映了系統(tǒng)當(dāng)前還有多少 “空閑資源” 可供使用。buff 和 cache 分別表示物理內(nèi)存用來(lái)緩存讀寫操作的 buffer 大小以及用來(lái)緩存進(jìn)程地址空間的 cache 大小 。

合理利用buffer和cache可以提高系統(tǒng)的IO性能,因?yàn)樗鼈兛梢詼p少對(duì)磁盤的直接讀寫次數(shù)。當(dāng)程序需要讀取數(shù)據(jù)時(shí),首先會(huì)在 cache 中查找,如果找到,就可以直接從 cache 中讀取,而無(wú)需訪問(wèn)磁盤,大大提高了數(shù)據(jù)讀取速度;同樣,當(dāng)程序需要寫入數(shù)據(jù)時(shí),數(shù)據(jù)會(huì)先寫入 buffer,然后由系統(tǒng)在適當(dāng)?shù)臅r(shí)候?qū)?buffer 中的數(shù)據(jù)寫入磁盤,這樣可以減少磁盤的隨機(jī)寫入次數(shù),提高寫入效率 。

swap 部分展示了系統(tǒng)的交換空間使用情況,si 表示每秒從磁盤讀入虛擬內(nèi)存的大小,so 表示每秒虛擬內(nèi)存寫入磁盤的大小 。當(dāng)內(nèi)存夠用時(shí),這兩個(gè)值通常都是 0。但如果這兩個(gè)值長(zhǎng)期大于 0,就像在一個(gè)繁忙的港口,貨物頻繁地裝卸,說(shuō)明系統(tǒng)在頻繁地進(jìn)行內(nèi)存和磁盤之間的數(shù)據(jù)交換,這會(huì)嚴(yán)重影響系統(tǒng)性能 。

io 部分提供了輸入輸出信息,bi 表示每秒從文件系統(tǒng)或 SWAP 讀入到 RAM(blocks in)的塊數(shù),bo 表示每秒從 RAM 寫出到文件系統(tǒng)或 SWAP(blocks out)的塊數(shù) 。在隨機(jī)磁盤讀寫操作中,如果這兩個(gè)值越大(如超出 1024k),就像高速公路上的車流量過(guò)大,能看到 CPU 在 IO 等待的值也會(huì)越大,這表明系統(tǒng)的 IO 性能可能存在瓶頸 。

system 部分呈現(xiàn)了系統(tǒng)信息,in 表示每秒的中斷數(shù),cs 表示系統(tǒng)每秒進(jìn)行上下文切換的次數(shù) 。上下文切換是指 CPU 從一個(gè)進(jìn)程或線程切換到另一個(gè)進(jìn)程或線程的過(guò)程,這個(gè)過(guò)程需要保存和恢復(fù)進(jìn)程或線程的上下文信息,會(huì)消耗一定的 CPU 資源。因此,cs 值越小越好,如果上下文切換次數(shù)過(guò)多,就像一個(gè)人頻繁地在不同任務(wù)之間切換,會(huì)導(dǎo)致 CPU 大部分時(shí)間浪費(fèi)在上下文切換上,真正用于執(zhí)行任務(wù)的時(shí)間就會(huì)減少 。

cpu 部分展示了 CPU 活動(dòng)的相關(guān)信息,us 表示用戶空間占用 CPU 的百分比,當(dāng) us 的值較高時(shí),說(shuō)明用戶進(jìn)程消耗的 CPU 時(shí)間比較多,如果長(zhǎng)期超過(guò) 50%,就像一個(gè)員工承擔(dān)了過(guò)多的工作任務(wù),我們就需要考慮優(yōu)化程序算法或者進(jìn)行加速,以提高 CPU 的使用效率 。sy 表示內(nèi)核空間占用 CPU 的百分比,sy 值高時(shí),說(shuō)明系統(tǒng)內(nèi)核消耗的 CPU 資源多,這可能是由于頻繁的系統(tǒng)調(diào)用、大量的 I/O 操作或者內(nèi)核模塊的性能問(wèn)題導(dǎo)致的,需要進(jìn)一步排查原因 。

id 表示 CPU 空閑的百分比,它反映了 CPU 當(dāng)前的空閑程度 。wa 表示 CPU 等待 IO 的百分比,wa 值高時(shí),說(shuō)明 CPU 在等待 I/O 操作完成的時(shí)間比較多,這可能是由于大量的磁盤隨機(jī)訪問(wèn)造成的,也有可能是磁盤出現(xiàn)瓶頸,需要對(duì)磁盤性能進(jìn)行優(yōu)化 。st 表示來(lái)自于虛擬機(jī)偷取的 CPU 所占的百分比,在虛擬化環(huán)境中,這個(gè)指標(biāo)對(duì)于評(píng)估虛擬機(jī)對(duì)物理機(jī) CPU 資源的占用情況非常重要 。

iostat 命令則是專門用于監(jiān)控系統(tǒng)設(shè)備的 IO 負(fù)載情況的 “專家”,它能為我們提供豐富的 IO 性能狀態(tài)數(shù)據(jù),幫助我們準(zhǔn)確判斷系統(tǒng)的 IO 性能瓶頸 。iostat 首次運(yùn)行時(shí),會(huì)顯示自系統(tǒng)啟動(dòng)開(kāi)始的各項(xiàng)統(tǒng)計(jì)信息,之后運(yùn)行 iostat 將顯示自上次運(yùn)行該命令以后的統(tǒng)計(jì)信息 。我們可以通過(guò)指定統(tǒng)計(jì)的次數(shù)和時(shí)間來(lái)獲得所需的統(tǒng)計(jì)信息,非常靈活方便 。

iostat 命令的輸出結(jié)果主要包括 CPU 信息和磁盤信息兩個(gè)部分 。在 CPU 信息部分,% user 表示用戶態(tài) CPU 占用百分比,% nice 表示 nice 優(yōu)先級(jí)較高的進(jìn)程的 CPU 占用百分比,% system 表示系統(tǒng)態(tài) CPU 占用百分比,% iowait 表示等待 I/O 的 CPU 占用百分比,% steal 表示虛擬機(jī)監(jiān)控器占用的 CPU 時(shí)間百分比(僅在虛擬化環(huán)境中出現(xiàn)),% idle 表示 CPU 空閑百分比 。這些指標(biāo)與 vmstat 中 CPU 部分的指標(biāo)類似,但 iostat 的輸出更加專注于 CPU 與 IO 相關(guān)的性能情況 。當(dāng) % iowait 值較高時(shí),說(shuō)明 CPU 在等待 I/O 操作的時(shí)間較長(zhǎng),這可能是磁盤讀寫速度過(guò)慢、I/O 設(shè)備繁忙或者 I/O 調(diào)度不合理等原因?qū)е碌?。

磁盤信息部分是 iostat 命令的重點(diǎn),它詳細(xì)展示了每個(gè)磁盤設(shè)備的性能指標(biāo) 。Device 表示磁盤設(shè)備的名稱,tps 表示每秒傳輸?shù)膲K數(shù)量,它反映了磁盤的 I/O 操作頻率,就像高速公路上每秒通過(guò)的車輛數(shù) 。kB_read/s 表示每秒從設(shè)備讀取的數(shù)據(jù)量,kB_wrtn/s 表示每秒向設(shè)備寫入的數(shù)據(jù)量,這兩個(gè)指標(biāo)直觀地展示了磁盤的讀寫速度 。kB_read 和 kB_wrtn 分別表示讀取和寫入的總數(shù)據(jù)量 。

此外,iostat 還可以通過(guò) - x 選項(xiàng)顯示更詳細(xì)的擴(kuò)展數(shù)據(jù),如 rrqm/s 表示每秒這個(gè)設(shè)備相關(guān)的讀取請(qǐng)求有多少被 Merge 了,wrqm/s 表示每秒這個(gè)設(shè)備相關(guān)的寫入請(qǐng)求有多少被 Merge 了,rsec/s 和 wsec/s 分別表示每秒讀取和寫入的扇區(qū)數(shù),avgrq-sz 表示平均請(qǐng)求扇區(qū)的大小,avgqu-sz 表示平均請(qǐng)求隊(duì)列的長(zhǎng)度,await 表示每一個(gè) IO 請(qǐng)求的處理的平均時(shí)間,svctm 表示平均每次設(shè)備 I/O 操作的服務(wù)時(shí)間,% util 表示在統(tǒng)計(jì)時(shí)間內(nèi)所有處理 IO 時(shí)間除以總共統(tǒng)計(jì)時(shí)間,它反映了設(shè)備的繁忙程度 。當(dāng) % util 接近 100% 時(shí),說(shuō)明磁盤設(shè)備已經(jīng)接近滿負(fù)荷運(yùn)行,可能會(huì)出現(xiàn) I/O 性能瓶頸 。

在實(shí)際應(yīng)用中,vmstat 和 iostat 常用于排查系統(tǒng)性能問(wèn)題。當(dāng)系統(tǒng)出現(xiàn)卡頓、響應(yīng)遲緩等問(wèn)題時(shí),我們可以先使用 vmstat 查看系統(tǒng)的整體運(yùn)行狀態(tài),包括 CPU、內(nèi)存、IO 等方面的情況,初步判斷問(wèn)題所在 。如果發(fā)現(xiàn) CPU 等待 IO 的時(shí)間較長(zhǎng),或者內(nèi)存使用異常,就可以進(jìn)一步使用 iostat 命令來(lái)深入分析磁盤的 IO 性能,找出具體是哪個(gè)磁盤設(shè)備出現(xiàn)了問(wèn)題,以及問(wèn)題的具體表現(xiàn),如讀寫速度過(guò)慢、請(qǐng)求隊(duì)列過(guò)長(zhǎng)等 。通過(guò)這些工具的配合使用,我們能夠更準(zhǔn)確地定位系統(tǒng)性能問(wèn)題的根源,為后續(xù)的優(yōu)化工作提供有力支持 。

2.3 perf:CPU 性能分析的專業(yè) “手術(shù)刀”

perf工具堪稱Linux系統(tǒng)中 CPU 性能分析的 “手術(shù)刀”,它功能強(qiáng)大,能夠利用處理器硬件性能監(jiān)控單元進(jìn)行性能事件采樣,幫助我們深入剖析程序的性能瓶頸,精確找出進(jìn)程的熱點(diǎn)函數(shù),是解決CPU性能問(wèn)題的得力助手 。

perf 工具基于硬件性能計(jì)數(shù)器(Hardware Performance Counters,HPC)工作,這些計(jì)數(shù)器是 CPU 內(nèi)部的特殊寄存器,就像一個(gè)個(gè)精密的傳感器,能夠記錄特定事件的發(fā)生次數(shù) 。perf 通過(guò)與 Linux 內(nèi)核的 perf_event 子系統(tǒng)交互,讀取這些計(jì)數(shù)器的值,從而獲取程序運(yùn)行時(shí)的各種性能數(shù)據(jù),如 CPU 利用率、緩存命中率、指令執(zhí)行次數(shù)等 。

perf 工具提供了豐富多樣的子命令,每個(gè)子命令都有其獨(dú)特的功能,就像一把把不同的手術(shù)刀,適用于不同的性能分析場(chǎng)景 。

perf list 子命令用于列出當(dāng)前系統(tǒng)支持的硬件性能事件、軟件事件和跟蹤點(diǎn) 。這就像一本詳細(xì)的 “性能事件字典”,當(dāng)我們需要進(jìn)行特定的性能分析時(shí),可以先使用 perf list 查看系統(tǒng)支持的事件類型,以便選擇合適的事件進(jìn)行采樣和分析 。例如,我們想要分析網(wǎng)絡(luò)相關(guān)的性能問(wèn)題,可以使用 “perf list 'net:*'” 命令查看所有與網(wǎng)絡(luò)相關(guān)的事件 。

perf top 子命令能夠?qū)崟r(shí)動(dòng)態(tài)地顯示系統(tǒng)中 CPU 占用最高的函數(shù) 。它就像一個(gè)實(shí)時(shí)的 “性能放大鏡”,讓我們能夠直觀地看到當(dāng)前系統(tǒng)中哪些函數(shù)正在大量消耗 CPU 資源 。在實(shí)際應(yīng)用中,當(dāng)系統(tǒng)出現(xiàn) CPU 使用率過(guò)高的情況時(shí),我們可以通過(guò) perf top 快速定位到占用 CPU 資源最多的函數(shù),進(jìn)而深入分析這些函數(shù)的代碼邏輯,找出性能瓶頸所在 。比如,在一個(gè)大型數(shù)據(jù)庫(kù)應(yīng)用中,通過(guò) perf top 發(fā)現(xiàn)某個(gè)查詢函數(shù)占用了大量 CPU 時(shí)間,經(jīng)過(guò)進(jìn)一步分析,發(fā)現(xiàn)是該函數(shù)中的查詢語(yǔ)句沒(méi)有使用合適的索引,導(dǎo)致全表掃描,從而消耗了大量 CPU 資源 。通過(guò)優(yōu)化查詢語(yǔ)句,添加合適的索引,成功降低了該函數(shù)的 CPU 占用率,提高了系統(tǒng)性能 。

perf stat 子命令用于統(tǒng)計(jì)程序運(yùn)行時(shí)的硬件事件,如緩存未命中、分支預(yù)測(cè)錯(cuò)誤等 。它就像一個(gè)精準(zhǔn)的 “性能計(jì)數(shù)器”,能夠幫助我們了解程序在運(yùn)行過(guò)程中的各種硬件事件發(fā)生情況 。通過(guò)分析這些事件的統(tǒng)計(jì)數(shù)據(jù),我們可以評(píng)估程序?qū)τ布Y源的利用效率,找出可能存在的性能問(wèn)題 。例如,我們可以使用 “perf stat -a -r 3 sleep 5” 命令對(duì)系統(tǒng)進(jìn)行全局統(tǒng)計(jì),統(tǒng)計(jì) 5 秒內(nèi)的硬件事件,并重復(fù) 3 次 。在輸出結(jié)果中,我們可以看到諸如 “cpu-clock”(CPU 時(shí)鐘周期)、“context-switches”(上下文切換次數(shù))、“page-faults”(頁(yè)面錯(cuò)誤次數(shù))等硬件事件的統(tǒng)計(jì)信息 。如果發(fā)現(xiàn)緩存未命中次數(shù)過(guò)高,說(shuō)明程序?qū)彺娴睦眯瘦^低,可能需要優(yōu)化程序的內(nèi)存訪問(wèn)模式,以提高緩存命中率 。

perf record 子命令用于記錄程序運(yùn)行時(shí)的性能事件,并將這些事件保存到一個(gè)文件(默認(rèn)為 perf.data)中,以便后續(xù)進(jìn)行詳細(xì)的性能分析 。它就像一個(gè)忠實(shí)的 “記錄員”,能夠準(zhǔn)確地記錄程序運(yùn)行時(shí)的各種性能細(xì)節(jié) 。我們可以使用 “perf record -g -F 99 -p 5678” 命令記錄 PID 為 5678 的進(jìn)程的調(diào)用圖,每秒采樣 99 次 。這樣,在程序運(yùn)行結(jié)束后,我們就可以通過(guò)其他子命令對(duì)保存的性能數(shù)據(jù)進(jìn)行分析 。

perf report 子命令用于分析 perf record 保存的性能事件,生成詳細(xì)的性能報(bào)告 。它就像一個(gè)專業(yè)的 “分析師”,能夠?qū)τ涗浀男阅軘?shù)據(jù)進(jìn)行深入解讀,展示程序中各個(gè)函數(shù)的性能消耗情況 。我們可以使用 “perf report -n --stdio” 命令以文本模式顯示樣本數(shù)量,也可以使用 “perf report -s symbol” 命令按函數(shù)名排序,以便更清晰地查看各個(gè)函數(shù)的性能情況 。在性能報(bào)告中,我們可以看到每個(gè)函數(shù)的 CPU 占用百分比、調(diào)用次數(shù)等信息,從而快速找出性能瓶頸所在的函數(shù) 。

perf script 子命令用于導(dǎo)出原始數(shù)據(jù),將 perf.data 文件轉(zhuǎn)換為文本格式 。這對(duì)于生成火焰圖或進(jìn)行自定義分析非常有用 ?;鹧鎴D是一種直觀展示程序性能的工具,它能夠以圖形化的方式呈現(xiàn)函數(shù)的調(diào)用關(guān)系和 CPU 占用情況 。我們可以使用 “perf script> out.stack” 命令將 perf.data 文件中的數(shù)據(jù)導(dǎo)出為調(diào)用棧數(shù)據(jù),然后使用相關(guān)工具生成火焰圖 。通過(guò)火焰圖,我們可以更直觀地看到程序中哪些函數(shù)調(diào)用頻繁,哪些函數(shù)占用 CPU 時(shí)間較長(zhǎng),從而有針對(duì)性地進(jìn)行性能優(yōu)化 。

在實(shí)際使用perf工具時(shí),我們可以根據(jù)具體的性能分析需求,靈活組合使用這些子命令 。例如,當(dāng)我們懷疑某個(gè)程序存在性能問(wèn)題時(shí),可以先使用perf top實(shí)時(shí)查看該程序中占用CPU資源最多的函數(shù),初步定位性能瓶頸 。然后,使用perfrecord記錄該程序運(yùn)行時(shí)的性能事件,并使用perf report對(duì)記錄的數(shù)據(jù)進(jìn)行分析,深入了解各個(gè)函數(shù)的性能消耗情況 。如果需要進(jìn)一步分析函數(shù)的調(diào)用關(guān)系和CPU占用的詳細(xì)情況,可以使用perf script導(dǎo)出原始數(shù)據(jù),生成火焰圖進(jìn)行分析 。

Part3.常見(jiàn)CPU性能問(wèn)題

3.1CPU 使用率過(guò)高

在 Linux 系統(tǒng)的日常運(yùn)行中,CPU 使用率過(guò)高是一種常見(jiàn)且棘手的問(wèn)題,它就像身體持續(xù)高燒不退,警示著系統(tǒng)內(nèi)部可能出現(xiàn)了嚴(yán)重的 “病癥”。導(dǎo)致 CPU 使用率過(guò)高的原因多種多樣,其中 CPU 密集型進(jìn)程是一個(gè)常見(jiàn)因素。這類進(jìn)程通常執(zhí)行大量的計(jì)算任務(wù),比如大數(shù)據(jù)分析程序在進(jìn)行復(fù)雜的數(shù)據(jù)計(jì)算和處理時(shí),會(huì)持續(xù)占用 CPU 資源,使得 CPU 使用率急劇上升。

死循環(huán)也是導(dǎo)致 CPU 使用率飆升的 “罪魁禍?zhǔn)住?之一。在程序編寫過(guò)程中,如果出現(xiàn)邏輯錯(cuò)誤導(dǎo)致死循環(huán),進(jìn)程會(huì)不斷地重復(fù)執(zhí)行相同的代碼,無(wú)法正常結(jié)束,從而將 CPU 資源緊緊 “鎖住”,使其無(wú)法分配給其他進(jìn)程。例如,在一段簡(jiǎn)單的 Python 代碼中,如果誤將循環(huán)條件設(shè)置錯(cuò)誤,就可能陷入死循環(huán):

i = 0
while i >= 0:
    i += 1

這個(gè)循環(huán)沒(méi)有設(shè)置合理的結(jié)束條件,會(huì)一直運(yùn)行下去,導(dǎo)致 CPU 使用率迅速達(dá)到 100%。

資源競(jìng)爭(zhēng)同樣會(huì)引發(fā) CPU 使用率過(guò)高的問(wèn)題。當(dāng)多個(gè)進(jìn)程同時(shí)競(jìng)爭(zhēng) CPU 資源時(shí),系統(tǒng)需要頻繁地進(jìn)行進(jìn)程調(diào)度和上下文切換,這會(huì)增加 CPU 的額外開(kāi)銷。以數(shù)據(jù)庫(kù)服務(wù)器為例,在高并發(fā)訪問(wèn)的情況下,多個(gè)查詢請(qǐng)求同時(shí)到達(dá),每個(gè)請(qǐng)求對(duì)應(yīng)的進(jìn)程都在爭(zhēng)奪 CPU 資源,導(dǎo)致 CPU 忙于處理這些調(diào)度任務(wù),使用率大幅提高。

針對(duì) CPU 使用率過(guò)高的問(wèn)題,我們可以采取一系列有效的優(yōu)化方法。從代碼層面入手,優(yōu)化算法和數(shù)據(jù)結(jié)構(gòu)是關(guān)鍵。對(duì)于一些復(fù)雜的計(jì)算任務(wù),通過(guò)改進(jìn)算法可以減少不必要的計(jì)算步驟,提高計(jì)算效率。例如,在排序算法中,選擇更高效的快速排序算法代替冒泡排序算法,能夠顯著降低計(jì)算時(shí)間和 CPU 消耗。同時(shí),合理使用緩存機(jī)制,避免重復(fù)計(jì)算,也能有效減少 CPU 的工作量。比如,在 Web 應(yīng)用中,對(duì)于一些頻繁訪問(wèn)且數(shù)據(jù)變動(dòng)較小的頁(yè)面或數(shù)據(jù),可以將其緩存起來(lái),當(dāng)再次請(qǐng)求時(shí)直接從緩存中獲取,而不需要重新進(jìn)行復(fù)雜的計(jì)算和數(shù)據(jù)庫(kù)查詢,從而降低 CPU 的使用率。

在系統(tǒng)層面,調(diào)整調(diào)度策略也是一種有效的優(yōu)化手段。Linux 系統(tǒng)提供了多種進(jìn)程調(diào)度算法,如完全公平調(diào)度算法(CFS)等。我們可以根據(jù)系統(tǒng)的實(shí)際負(fù)載情況和應(yīng)用需求,調(diào)整調(diào)度算法的參數(shù),以優(yōu)化 CPU 資源的分配。例如,對(duì)于一些對(duì)實(shí)時(shí)性要求較高的應(yīng)用程序,如視頻直播、實(shí)時(shí)監(jiān)控等,可以適當(dāng)提高其進(jìn)程的優(yōu)先級(jí),使其能夠優(yōu)先獲得 CPU 資源,保證應(yīng)用的流暢運(yùn)行;而對(duì)于一些后臺(tái)批處理任務(wù),可以降低其優(yōu)先級(jí),讓它們?cè)?CPU 空閑時(shí)再執(zhí)行,避免與前臺(tái)關(guān)鍵任務(wù)爭(zhēng)搶資源。

當(dāng)系統(tǒng)資源確實(shí)不足時(shí),增加 CPU 資源也是一種直接有效的解決方法??梢酝ㄟ^(guò)升級(jí)硬件,增加 CPU 核心數(shù)或更換更高性能的 CPU 來(lái)滿足系統(tǒng)的計(jì)算需求。例如,對(duì)于一些大型企業(yè)的服務(wù)器,隨著業(yè)務(wù)量的不斷增長(zhǎng),原有的 CPU 配置可能無(wú)法滿足日益增長(zhǎng)的計(jì)算需求,此時(shí)可以考慮增加 CPU 核心數(shù)或者更換為更高級(jí)的 CPU 型號(hào),以提升系統(tǒng)的整體性能。

3.2平均負(fù)載過(guò)高

平均負(fù)載過(guò)高是另一個(gè)需要關(guān)注的 CPU 性能問(wèn)題,它反映了系統(tǒng)在一段時(shí)間內(nèi)的繁忙程度和壓力狀況。當(dāng)平均負(fù)載持續(xù)高于系統(tǒng) CPU 核心數(shù)時(shí),說(shuō)明系統(tǒng)正面臨著較大的壓力,可能會(huì)出現(xiàn)性能下降甚至服務(wù)中斷的風(fēng)險(xiǎn)。

導(dǎo)致平均負(fù)載過(guò)高的因素較為復(fù)雜,進(jìn)程阻塞是其中之一。當(dāng)進(jìn)程在執(zhí)行過(guò)程中等待某些資源(如 I/O 操作、鎖資源等)時(shí),會(huì)進(jìn)入阻塞狀態(tài),此時(shí)雖然進(jìn)程不占用 CPU 執(zhí)行時(shí)間,但會(huì)使系統(tǒng)的平均負(fù)載增加。例如,當(dāng)一個(gè)進(jìn)程需要從磁盤讀取大量數(shù)據(jù)時(shí),如果磁盤 I/O 速度較慢,進(jìn)程就會(huì)在等待數(shù)據(jù)讀取的過(guò)程中處于阻塞狀態(tài),導(dǎo)致系統(tǒng)中可運(yùn)行的進(jìn)程數(shù)量減少,平均負(fù)載升高。

I/O 等待也是導(dǎo)致平均負(fù)載過(guò)高的常見(jiàn)原因。在系統(tǒng)進(jìn)行大量的 I/O 操作(如磁盤讀寫、網(wǎng)絡(luò)通信等)時(shí),如果 I/O 設(shè)備的性能瓶頸限制了數(shù)據(jù)傳輸速度,進(jìn)程就需要花費(fèi)大量時(shí)間等待 I/O 操作完成,這會(huì)使 CPU 處于空閑狀態(tài),但平均負(fù)載卻在不斷上升。比如,在一個(gè)頻繁進(jìn)行文件讀寫操作的服務(wù)器上,如果磁盤的讀寫速度跟不上進(jìn)程的請(qǐng)求速度,就會(huì)出現(xiàn)大量的 I/O 等待,導(dǎo)致平均負(fù)載過(guò)高。

CPU 資源不足同樣會(huì)導(dǎo)致平均負(fù)載過(guò)高。當(dāng)系統(tǒng)中運(yùn)行的進(jìn)程數(shù)量過(guò)多,而 CPU 核心數(shù)有限時(shí),進(jìn)程之間會(huì)競(jìng)爭(zhēng) CPU 資源,導(dǎo)致部分進(jìn)程長(zhǎng)時(shí)間處于等待狀態(tài),從而使平均負(fù)載升高。例如,在一個(gè)小型服務(wù)器上同時(shí)運(yùn)行多個(gè)大型應(yīng)用程序,由于 CPU 資源有限,這些應(yīng)用程序的進(jìn)程會(huì)不斷爭(zhēng)搶 CPU,導(dǎo)致平均負(fù)載持續(xù)上升。

針對(duì)平均負(fù)載過(guò)高的問(wèn)題,我們可以采取多種解決措施。優(yōu)化 I/O 是關(guān)鍵一步,通過(guò)使用高性能的 I/O 設(shè)備,如固態(tài)硬盤(SSD)代替?zhèn)鹘y(tǒng)機(jī)械硬盤,可以顯著提高 I/O 讀寫速度,減少 I/O 等待時(shí)間,從而降低平均負(fù)載。同時(shí),合理調(diào)整 I/O 調(diào)度算法,根據(jù)應(yīng)用的特點(diǎn)選擇合適的調(diào)度策略,也能提高 I/O 性能。例如,對(duì)于數(shù)據(jù)庫(kù)應(yīng)用,選擇 Deadline 調(diào)度算法可以更好地滿足其對(duì) I/O 響應(yīng)時(shí)間的要求。

調(diào)整進(jìn)程優(yōu)先級(jí)也是一種有效的方法。通過(guò)提升關(guān)鍵進(jìn)程的優(yōu)先級(jí),確保它們能夠優(yōu)先獲得 CPU 資源,及時(shí)完成任務(wù),從而降低系統(tǒng)的平均負(fù)載。例如,對(duì)于一個(gè)同時(shí)運(yùn)行 Web 服務(wù)器和后臺(tái)數(shù)據(jù)備份任務(wù)的系統(tǒng),可以將 Web 服務(wù)器進(jìn)程的優(yōu)先級(jí)設(shè)置為較高,保證用戶的請(qǐng)求能夠得到及時(shí)響應(yīng),而將數(shù)據(jù)備份任務(wù)的優(yōu)先級(jí)設(shè)置為較低,讓它在系統(tǒng)空閑時(shí)再執(zhí)行。

優(yōu)化系統(tǒng)配置同樣不可或缺。合理調(diào)整系統(tǒng)參數(shù),如增大文件系統(tǒng)緩存、優(yōu)化內(nèi)存分配等,可以提高系統(tǒng)的整體性能,緩解平均負(fù)載過(guò)高的問(wèn)題。例如,通過(guò)增大系統(tǒng)的文件系統(tǒng)緩存,可以減少磁盤 I/O 操作的次數(shù),提高數(shù)據(jù)訪問(wèn)速度,從而降低平均負(fù)載。

3.3進(jìn)程 CPU 占用不均衡

在 Linux 系統(tǒng)中,進(jìn)程 CPU 占用不均衡也是一種常見(jiàn)的性能問(wèn)題,它表現(xiàn)為部分進(jìn)程占用大量 CPU 資源,而其他進(jìn)程卻無(wú)法充分利用 CPU,導(dǎo)致系統(tǒng)資源分配不合理,整體性能下降。

造成進(jìn)程 CPU 占用不均衡的原因主要有程序設(shè)計(jì)不合理和資源分配不均等。在程序設(shè)計(jì)方面,如果開(kāi)發(fā)者沒(méi)有充分考慮多線程或多進(jìn)程的資源分配和調(diào)度問(wèn)題,可能會(huì)導(dǎo)致某些線程或進(jìn)程過(guò)度占用 CPU。例如,在一個(gè)多線程的網(wǎng)絡(luò)爬蟲(chóng)程序中,如果沒(méi)有對(duì)各個(gè)線程的任務(wù)進(jìn)行合理分配和協(xié)調(diào),可能會(huì)出現(xiàn)某些線程頻繁發(fā)起網(wǎng)絡(luò)請(qǐng)求并進(jìn)行數(shù)據(jù)處理,占用大量 CPU 資源,而其他線程則處于空閑狀態(tài)。

資源分配不均也是導(dǎo)致進(jìn)程 CPU 占用不均衡的重要因素。當(dāng)系統(tǒng)資源(如內(nèi)存、I/O 等)分配不合理時(shí),會(huì)使得某些進(jìn)程在獲取資源時(shí)處于優(yōu)勢(shì)地位,從而能夠占用更多的 CPU 資源。比如,在一個(gè)共享內(nèi)存的多進(jìn)程應(yīng)用中,如果某個(gè)進(jìn)程占用了過(guò)多的內(nèi)存,導(dǎo)致其他進(jìn)程在進(jìn)行內(nèi)存訪問(wèn)時(shí)出現(xiàn)頻繁的頁(yè)錯(cuò)誤,這些進(jìn)程就需要花費(fèi)更多的 CPU 時(shí)間來(lái)處理這些錯(cuò)誤,從而導(dǎo)致 CPU 占用不均衡。

為了解決進(jìn)程 CPU 占用不均衡的問(wèn)題,我們可以采取以下優(yōu)化方式。調(diào)整進(jìn)程綁定 CPU 是一種有效的方法,通過(guò)使用 taskset 命令或在程序中設(shè)置 CPU 親和性,將特定的進(jìn)程綁定到指定的 CPU 核心上,避免進(jìn)程在多個(gè) CPU 核心之間頻繁切換,從而提高 CPU 的使用效率。例如,對(duì)于一個(gè)計(jì)算密集型的進(jìn)程,可以將其綁定到一個(gè)空閑的 CPU 核心上,讓它充分利用該核心的資源,避免與其他進(jìn)程爭(zhēng)搶資源。

優(yōu)化資源分配算法也是關(guān)鍵。在程序設(shè)計(jì)中,合理設(shè)計(jì)資源分配算法,確保各個(gè)進(jìn)程能夠公平地獲取系統(tǒng)資源,避免資源過(guò)度集中在某些進(jìn)程上。例如,在一個(gè)多進(jìn)程的任務(wù)調(diào)度系統(tǒng)中,可以采用輪詢或優(yōu)先級(jí)隊(duì)列等方式來(lái)分配任務(wù)和資源,保證每個(gè)進(jìn)程都有機(jī)會(huì)獲得 CPU 資源,實(shí)現(xiàn)資源的均衡分配。

Part4.優(yōu)化實(shí)戰(zhàn)策略

在深入了解了 CPU 性能指標(biāo)以及排查出性能問(wèn)題的 “元兇” 后,接下來(lái)就到了關(guān)鍵的優(yōu)化實(shí)戰(zhàn)環(huán)節(jié)。這就好比醫(yī)生在準(zhǔn)確診斷出病人的病因后,開(kāi)始對(duì)癥下藥進(jìn)行治療。下面,我們將從進(jìn)程調(diào)度、CPU 頻率調(diào)整以及應(yīng)用程序優(yōu)化這三個(gè)關(guān)鍵方面入手,為 Linux 系統(tǒng)的 CPU 性能 “插上翅膀” 。

4.1進(jìn)程調(diào)度優(yōu)化:合理分配 CPU “蛋糕”

Linux 進(jìn)程調(diào)度器就像是一位精明的資源分配者,負(fù)責(zé)管理系統(tǒng)中進(jìn)程對(duì) CPU 資源的使用。它的工作原理基于一系列復(fù)雜而精妙的算法,旨在確保系統(tǒng)高效、穩(wěn)定地運(yùn)行,同時(shí)兼顧各個(gè)進(jìn)程的公平性和響應(yīng)性 。

在 Linux 系統(tǒng)中,常見(jiàn)的調(diào)度算法有多種,每種算法都有其獨(dú)特的設(shè)計(jì)理念和適用場(chǎng)景 。先來(lái)先服務(wù)(FCFS)算法按照進(jìn)程到達(dá)就緒隊(duì)列的先后順序來(lái)分配 CPU,簡(jiǎn)單直觀,如同排隊(duì)買票,先到先得 。但它存在明顯的缺陷,若一個(gè)長(zhǎng)進(jìn)程先到達(dá)并占用 CPU,后面的短進(jìn)程就只能苦苦等待,導(dǎo)致整體效率低下,就像前面有個(gè)購(gòu)物清單很長(zhǎng)的顧客在結(jié)賬,后面的顧客都得等很久 。這種算法適用于批處理系統(tǒng)中任務(wù)序列簡(jiǎn)單、對(duì)響應(yīng)時(shí)間要求不高的場(chǎng)景 。

短作業(yè)優(yōu)先(SJF)算法則優(yōu)先調(diào)度估計(jì)運(yùn)行時(shí)間最短的進(jìn)程,能有效降低平均周轉(zhuǎn)時(shí)間,提高系統(tǒng)吞吐量 。然而,準(zhǔn)確預(yù)估進(jìn)程的運(yùn)行時(shí)間并非易事,而且長(zhǎng)進(jìn)程可能會(huì)因?yàn)椴粩嘤卸踢M(jìn)程進(jìn)入而長(zhǎng)時(shí)間得不到執(zhí)行,出現(xiàn) “饑餓” 現(xiàn)象 。比如在一個(gè)數(shù)據(jù)處理中心,有大量不同數(shù)據(jù)量的任務(wù),小數(shù)據(jù)量的短任務(wù)可以用 SJF 算法快速處理,提升整體效率,但長(zhǎng)任務(wù)可能會(huì)被忽視 。它比較適合分時(shí)系統(tǒng)中短任務(wù)處理以及小型服務(wù)器的日常請(qǐng)求處理等場(chǎng)景 。

時(shí)間片輪轉(zhuǎn)(RR)算法將 CPU 的處理時(shí)間劃分為固定長(zhǎng)度的時(shí)間片,所有就緒進(jìn)程按照順序輪流在 CPU 上運(yùn)行一個(gè)時(shí)間片 。當(dāng)時(shí)間片用完,進(jìn)程無(wú)論是否完成任務(wù),都會(huì)被暫停并放回就緒隊(duì)列末尾,等待下一輪調(diào)度 。這就像一場(chǎng)接力賽,每個(gè)進(jìn)程都有機(jī)會(huì)在規(guī)定時(shí)間內(nèi) “跑一段”,保證了每個(gè)進(jìn)程都能得到處理,具有很好的公平性 。但如果時(shí)間片設(shè)置過(guò)小,會(huì)導(dǎo)致頻繁的上下文切換,增加系統(tǒng)開(kāi)銷;若時(shí)間片過(guò)大,又會(huì)退化成先來(lái)先服務(wù)算法,無(wú)法體現(xiàn)其優(yōu)勢(shì) 。時(shí)間片輪轉(zhuǎn)算法廣泛應(yīng)用于分時(shí)系統(tǒng)和交互式系統(tǒng),比如多用戶的服務(wù)器環(huán)境,能讓每個(gè)用戶的進(jìn)程都快速獲得 CPU 服務(wù),提升用戶體驗(yàn) 。

優(yōu)先級(jí)調(diào)度算法為每個(gè)進(jìn)程分配一個(gè)優(yōu)先級(jí),優(yōu)先級(jí)高的進(jìn)程優(yōu)先執(zhí)行 。這就像在醫(yī)院里,急診病人會(huì)比普通病人優(yōu)先得到救治 。該算法能保證高優(yōu)先級(jí)任務(wù)及時(shí)執(zhí)行,但可能出現(xiàn) “優(yōu)先級(jí)反轉(zhuǎn)” 和 “饑餓” 問(wèn)題,即低優(yōu)先級(jí)進(jìn)程占用資源,導(dǎo)致高優(yōu)先級(jí)進(jìn)程無(wú)法執(zhí)行,或者某些進(jìn)程長(zhǎng)時(shí)間得不到調(diào)度 。為緩解這些問(wèn)題,可以引入老化機(jī)制,逐漸提高長(zhǎng)時(shí)間等待進(jìn)程的優(yōu)先級(jí) 。它適用于對(duì)任務(wù)優(yōu)先級(jí)有嚴(yán)格要求的實(shí)時(shí)系統(tǒng),如工業(yè)自動(dòng)化控制、航空航天等領(lǐng)域 。

多級(jí)反饋隊(duì)列調(diào)度算法結(jié)合了多種算法的優(yōu)點(diǎn),將進(jìn)程分配到多個(gè)優(yōu)先級(jí)隊(duì)列中,每個(gè)隊(duì)列有不同的時(shí)間片長(zhǎng)度和優(yōu)先級(jí) 。優(yōu)先級(jí)高的隊(duì)列時(shí)間片較短,優(yōu)先處理高優(yōu)先級(jí)隊(duì)列的進(jìn)程 。在任務(wù)執(zhí)行過(guò)程中,還可以動(dòng)態(tài)調(diào)整優(yōu)先級(jí),長(zhǎng)時(shí)間等待的低優(yōu)先級(jí)進(jìn)程會(huì)被提升到更高優(yōu)先級(jí)隊(duì)列,避免長(zhǎng)作業(yè) “饑餓” 。這種算法雖然復(fù)雜,管理多個(gè)隊(duì)列需要額外開(kāi)銷,但能高效處理不同類型的任務(wù),適用于需要高響應(yīng)速度和公平性的操作系統(tǒng) 。

在實(shí)際應(yīng)用中,我們可以通過(guò)調(diào)整進(jìn)程優(yōu)先級(jí)來(lái)優(yōu)化調(diào)度策略 。在 Linux 系統(tǒng)中,可以使用 nice 和 renice 命令來(lái)調(diào)整進(jìn)程的 nice 值,從而改變進(jìn)程的優(yōu)先級(jí) 。nice 值的范圍是 - 20 到 19,值越小優(yōu)先級(jí)越高 。例如,使用 nice -n -5 command 命令可以以較高優(yōu)先級(jí)啟動(dòng)一個(gè)新進(jìn)程;對(duì)于已經(jīng)運(yùn)行的進(jìn)程,使用 renice -n 10 -p pid 命令可以將進(jìn)程 ID 為 pid 的進(jìn)程優(yōu)先級(jí)降低 。對(duì)于實(shí)時(shí)進(jìn)程,還可以使用 chrt 命令設(shè)置調(diào)度策略和優(yōu)先級(jí) 。比如,sudo chrt -f 50 command 命令可以將程序以實(shí)時(shí) FIFO 策略運(yùn)行,并設(shè)置優(yōu)先級(jí)為 50 。在調(diào)整進(jìn)程優(yōu)先級(jí)時(shí),需要注意權(quán)限問(wèn)題,普通用戶只能提高進(jìn)程的 nice 值(降低優(yōu)先級(jí)),設(shè)置低于 0 的 nice 值或?qū)崟r(shí)優(yōu)先級(jí)需要超級(jí)用戶權(quán)限 。同時(shí),要謹(jǐn)慎調(diào)整優(yōu)先級(jí),不當(dāng)?shù)脑O(shè)置可能會(huì)導(dǎo)致系統(tǒng)不穩(wěn)定或響應(yīng)變慢 。

4.2CPU 頻率調(diào)整:動(dòng)態(tài)調(diào)節(jié) CPU “馬力”

CPU頻率就像是汽車的發(fā)動(dòng)機(jī)轉(zhuǎn)速,直接影響著CPU的運(yùn)算速度和性能表現(xiàn) 。在 Linux 系統(tǒng)中,我們可以根據(jù)系統(tǒng)負(fù)載的變化,動(dòng)態(tài)調(diào)整 CPU 頻率,實(shí)現(xiàn)性能和功耗的平衡,讓CPU在不同的工作場(chǎng)景下都能發(fā)揮出最佳效能 。

CPU 頻率調(diào)整的原理基于現(xiàn)代 CPU 的動(dòng)態(tài)頻率調(diào)整(DFA)技術(shù) 。CPU 內(nèi)部有一個(gè)智能的頻率調(diào)節(jié)器,它就像一位經(jīng)驗(yàn)豐富的駕駛員,時(shí)刻監(jiān)測(cè)著 CPU 的工作負(fù)載 。當(dāng)負(fù)載較低時(shí),比如系統(tǒng)處于待機(jī)狀態(tài)或只運(yùn)行一些簡(jiǎn)單的后臺(tái)任務(wù),頻率調(diào)節(jié)器會(huì)降低 CPU 頻率,就像汽車在空路上行駛時(shí)降低發(fā)動(dòng)機(jī)轉(zhuǎn)速,以節(jié)省能耗 。相反,當(dāng)負(fù)載較高,如運(yùn)行大型游戲、進(jìn)行復(fù)雜的數(shù)據(jù)分析或編譯大型程序時(shí),頻率調(diào)節(jié)器會(huì)提高 CPU 頻率,讓 CPU 全力運(yùn)轉(zhuǎn),提供更好的性能,如同汽車在爬坡或高速行駛時(shí)提高發(fā)動(dòng)機(jī)轉(zhuǎn)速 。

在 Linux 系統(tǒng)中,我們可以使用 cpupower 工具來(lái)實(shí)現(xiàn) CPU 頻率的調(diào)整 。cpupower 工具功能強(qiáng)大,提供了豐富的命令選項(xiàng),讓我們能夠靈活地管理 CPU 的電源和性能選項(xiàng) 。在使用 cpupower 工具之前,首先需要確保它已經(jīng)安裝在系統(tǒng)中 。對(duì)于基于 Debian 的系統(tǒng)(如 Ubuntu),可以使用 sudo apt-get install linux-tools-common linux-tools-generic linux-tools-$(uname -r) 命令進(jìn)行安裝;對(duì)于基于 RPM 的系統(tǒng)(如 Fedora 或 CentOS),可以使用 sudo yum install cpupower 或 sudo dnf install cpupower 命令進(jìn)行安裝 。

安裝完成后,我們可以使用 cpupower frequency-info 命令來(lái)查看CPU頻率的相關(guān)信息,包括當(dāng)前 CPU 的運(yùn)行頻率、支持的頻率范圍、可用的頻率調(diào)節(jié)策略等 。例如,執(zhí)行該命令后,我們可能會(huì)看到類似如下的輸出:

analyzing CPU 0:
  driver: intel_pstate
  CPUs which run at the same hardware frequency: 0
  CPUs which need to have their frequency coordinated by software: 0
  maximum transition latency:  Cannot determine or is not supported.
  hardware limits: 800 MHz - 4.00 GHz
  available cpufreq governors: performance powersave
  current policy: frequency should be within 800 MHz and 4.00 GHz.
                  The governor "powersave" may decide which speed to use
                  within this range.
  current CPU frequency is 800 MHz.
  cpufreq stats: 800 MHz:10.00%, 4.00 GHz:90.00%  (10000)

從輸出信息中,我們可以了解到當(dāng)前 CPU 的驅(qū)動(dòng)為 intel_pstate,硬件支持的頻率范圍是 800 MHz - 4.00 GHz,可用的頻率調(diào)節(jié)策略有 performance 和 powersave,當(dāng)前采用的是 powersave 策略,CPU 頻率為 800 MHz,并且還能看到不同頻率下的使用統(tǒng)計(jì)信息 。

接下來(lái),我們可以根據(jù)實(shí)際需求,使用 cpupower frequency-set 命令來(lái)設(shè)置 CPU 的頻率調(diào)節(jié)策略 。如果我們希望系統(tǒng)在任何情況下都能以最高性能運(yùn)行,比如在進(jìn)行大型數(shù)據(jù)庫(kù)查詢、3D 圖形渲染等對(duì)性能要求極高的任務(wù)時(shí),可以使用 sudo cpupower frequency-set -g performance 命令將頻率調(diào)節(jié)策略設(shè)置為 performance 。在這種策略下,CPU 會(huì)始終運(yùn)行在最高頻率,以提供最強(qiáng)的計(jì)算能力,但相應(yīng)地,功耗也會(huì)增加,就像汽車始終保持高速行駛,油耗會(huì)上升 。

相反,如果我們更注重節(jié)能,比如在筆記本電腦使用電池供電時(shí),希望延長(zhǎng)電池續(xù)航時(shí)間,可以使用 sudo cpupower frequency-set -g powersave 命令將頻率調(diào)節(jié)策略設(shè)置為 powersave 。在 powersave 策略下,CPU 會(huì)根據(jù)負(fù)載自動(dòng)降低頻率,以減少功耗,就像汽車在經(jīng)濟(jì)模式下行駛,發(fā)動(dòng)機(jī)轉(zhuǎn)速較低,油耗也較低 。

除了這兩種常見(jiàn)的策略,Linux 系統(tǒng)還支持其他一些頻率調(diào)節(jié)策略,如 ondemand 和 conservative 。ondemand 策略會(huì)根據(jù) CPU 的負(fù)載情況動(dòng)態(tài)調(diào)整頻率,當(dāng)負(fù)載增加時(shí),快速提高頻率;當(dāng)負(fù)載降低時(shí),迅速降低頻率 。它在性能和功耗之間取得了較好的平衡,適用于大多數(shù)日常使用場(chǎng)景,就像一個(gè)智能的駕駛員,根據(jù)路況靈活調(diào)整車速 。conservative 策略與 ondemand 類似,但頻率調(diào)整相對(duì)更為保守,不會(huì)像 ondemand 那樣快速地改變頻率,適用于對(duì)頻率變化較為敏感的應(yīng)用程序 。

在實(shí)際應(yīng)用中,根據(jù)系統(tǒng)負(fù)載動(dòng)態(tài)調(diào)整 CPU 頻率能帶來(lái)顯著的好處 。在服務(wù)器環(huán)境中,當(dāng)業(yè)務(wù)量較低時(shí),將 CPU 頻率降低,可以節(jié)省大量的電力成本,減少服務(wù)器的散熱壓力,延長(zhǎng)硬件的使用壽命 。而當(dāng)業(yè)務(wù)量突然增加,如電商網(wǎng)站在促銷活動(dòng)期間,將 CPU 頻率提高,能夠保證系統(tǒng)的響應(yīng)速度,避免因性能不足而導(dǎo)致用戶流失 。在移動(dòng)設(shè)備上,合理調(diào)整 CPU 頻率更是至關(guān)重要,它可以在保證用戶體驗(yàn)的前提下,最大限度地延長(zhǎng)電池續(xù)航時(shí)間,讓用戶能夠更長(zhǎng)久地使用設(shè)備 。

4.3應(yīng)用程序優(yōu)化:從源頭提升 CPU 效率

應(yīng)用程序作為 CPU 資源的主要使用者,其代碼質(zhì)量和算法設(shè)計(jì)對(duì) CPU 性能有著深遠(yuǎn)的影響 。從代碼層面深入分析影響 CPU 性能的因素,并采取有效的優(yōu)化措施,是提升 CPU 效率的關(guān)鍵所在,就像從源頭上治理河流污染,才能讓河水清澈見(jiàn)底 。

算法復(fù)雜度是影響 CPU 性能的重要因素之一 。簡(jiǎn)單來(lái)說(shuō),算法復(fù)雜度描述了算法執(zhí)行所需的時(shí)間和空間資源隨著輸入規(guī)模增長(zhǎng)的變化情況 。常見(jiàn)的算法復(fù)雜度有 O (1)、O (n)、O (n^2)、O (log n) 等 。以查找算法為例,線性查找算法的時(shí)間復(fù)雜度為 O (n),它需要遍歷整個(gè)數(shù)據(jù)集合來(lái)查找目標(biāo)元素 。當(dāng)數(shù)據(jù)規(guī)模 n 很大時(shí),如在一個(gè)包含百萬(wàn)條記錄的數(shù)據(jù)庫(kù)中進(jìn)行線性查找,CPU 需要執(zhí)行大量的比較操作,消耗大量時(shí)間 。而二分查找算法的時(shí)間復(fù)雜度為 O (log n),它利用數(shù)據(jù)有序的特點(diǎn),每次比較都能排除一半的數(shù)據(jù),查找速度大大加快 。在一個(gè)同樣規(guī)模的有序數(shù)據(jù)集中,二分查找的效率要遠(yuǎn)遠(yuǎn)高于線性查找,對(duì) CPU 資源的消耗也更少 。因此,在編寫應(yīng)用程序時(shí),我們應(yīng)盡量選擇復(fù)雜度較低的算法,避免使用那些隨著數(shù)據(jù)規(guī)模增長(zhǎng),時(shí)間和空間復(fù)雜度急劇上升的算法,以減少 CPU 的計(jì)算量 。

循環(huán)嵌套也是一個(gè)容易導(dǎo)致 CPU 性能問(wèn)題的因素 。當(dāng)循環(huán)嵌套層數(shù)過(guò)多時(shí),就像一個(gè)迷宮中有很多層嵌套的房間,CPU 需要執(zhí)行大量的循環(huán)迭代,計(jì)算量呈指數(shù)級(jí)增長(zhǎng) 。例如,一個(gè)三層嵌套的循環(huán),最內(nèi)層循環(huán)的執(zhí)行次數(shù)等于三層循環(huán)各自迭代次數(shù)的乘積 。如果每層循環(huán)都迭代 100 次,那么最內(nèi)層循環(huán)將執(zhí)行 100 * 100 * 100 = 1000000 次,這對(duì) CPU 來(lái)說(shuō)是一個(gè)巨大的負(fù)擔(dān) 。為了優(yōu)化循環(huán)嵌套,我們可以盡量減少不必要的循環(huán)層數(shù),將一些重復(fù)的計(jì)算移出循環(huán)體,或者使用更高效的算法來(lái)替代嵌套循環(huán) 。比如,在計(jì)算矩陣乘法時(shí),傳統(tǒng)的三重循環(huán)實(shí)現(xiàn)雖然直觀,但效率較低 。我們可以通過(guò)優(yōu)化算法,利用矩陣的分塊技術(shù),將大矩陣分成多個(gè)小矩陣進(jìn)行計(jì)算,減少循環(huán)次數(shù),提高計(jì)算效率,從而降低 CPU 的占用 。

除了算法復(fù)雜度和循環(huán)嵌套,代碼中的其他一些細(xì)節(jié)也會(huì)影響 CPU 性能 。頻繁的函數(shù)調(diào)用會(huì)帶來(lái)一定的開(kāi)銷,因?yàn)槊看魏瘮?shù)調(diào)用都需要保存和恢復(fù)寄存器狀態(tài)、創(chuàng)建和銷毀棧幀等 。因此,我們可以盡量減少不必要的函數(shù)調(diào)用,將一些短小的函數(shù)定義為內(nèi)聯(lián)函數(shù),這樣在編譯時(shí),函數(shù)代碼會(huì)直接嵌入調(diào)用處,避免了函數(shù)調(diào)用的開(kāi)銷 。內(nèi)存訪問(wèn)模式也對(duì) CPU 性能有重要影響 。CPU 緩存是提高內(nèi)存訪問(wèn)速度的關(guān)鍵,如果代碼中的內(nèi)存訪問(wèn)模式不合理,導(dǎo)致頻繁的緩存未命中,就會(huì)大大降低內(nèi)存訪問(wèn)速度,進(jìn)而影響 CPU 性能 。我們應(yīng)盡量保持內(nèi)存訪問(wèn)的連續(xù)性,避免隨機(jī)訪問(wèn)內(nèi)存,以提高緩存命中率 。

在實(shí)際的應(yīng)用程序優(yōu)化中,有許多成功的案例可供我們借鑒 。在一個(gè)大數(shù)據(jù)分析項(xiàng)目中,最初的數(shù)據(jù)分析算法使用了復(fù)雜的遞歸算法,雖然代碼簡(jiǎn)潔,但在處理大規(guī)模數(shù)據(jù)時(shí),CPU 占用率極高,處理時(shí)間很長(zhǎng) 。通過(guò)深入分析算法,開(kāi)發(fā)團(tuán)隊(duì)將遞歸算法改為迭代算法,并對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行了優(yōu)化,減少了不必要的內(nèi)存操作 。優(yōu)化后的程序在處理相同規(guī)模的數(shù)據(jù)時(shí),CPU 占用率降低了 50% 以上,處理時(shí)間縮短了近三分之二,大大提高了數(shù)據(jù)分析的效率 。在一個(gè)圖形渲染應(yīng)用中,原來(lái)的代碼存在大量的循環(huán)嵌套和重復(fù)計(jì)算,導(dǎo)致在渲染復(fù)雜場(chǎng)景時(shí),畫面卡頓嚴(yán)重 。開(kāi)發(fā)人員對(duì)代碼進(jìn)行了重構(gòu),將一些常用的計(jì)算結(jié)果緩存起來(lái),避免重復(fù)計(jì)算,同時(shí)優(yōu)化了循環(huán)結(jié)構(gòu),減少了循環(huán)層數(shù) 。經(jīng)過(guò)優(yōu)化后,圖形渲染的幀率得到了顯著提升,畫面更加流暢,用戶體驗(yàn)得到了極大改善 。

綜上所述,從代碼層面優(yōu)化應(yīng)用程序是提升 CPU 效率的重要途徑 。通過(guò)選擇合適的算法、優(yōu)化循環(huán)結(jié)構(gòu)、減少函數(shù)調(diào)用開(kāi)銷、改善內(nèi)存訪問(wèn)模式等措施,我們能夠讓應(yīng)用程序更加高效地利用 CPU 資源,從而提升整個(gè)系統(tǒng)的性能 。在實(shí)際開(kāi)發(fā)過(guò)程中,我們應(yīng)養(yǎng)成良好的編程習(xí)慣,注重代碼的性能優(yōu)化,從源頭上為 CPU 性能的提升奠定堅(jiān)實(shí)的基礎(chǔ) 。

Part5.CPU性能分析工具實(shí)操

5.1Stress:制造負(fù)載的 “小能手”

在進(jìn)行 CPU 性能優(yōu)化時(shí),我們首先需要一種工具來(lái)模擬系統(tǒng)高負(fù)載的情況,以便觀察和分析 CPU 在不同壓力下的表現(xiàn),Stress 就是這樣一位得力助手。Stress 是一款專為 Linux 系統(tǒng)設(shè)計(jì)的壓力測(cè)試工具,它能夠模擬各種資源消耗場(chǎng)景,幫助我們?cè)u(píng)估系統(tǒng)在高負(fù)載下的穩(wěn)定性和性能極限,特別適合在測(cè)試環(huán)境中使用 。

假設(shè)我們要模擬一個(gè)高 CPU 密集的場(chǎng)景,只需在終端輸入 “stress -c 4” 命令,這里的 “-c” 參數(shù)表示創(chuàng)建 CPU 負(fù)載,數(shù)字 “4” 則指定了要?jiǎng)?chuàng)建 4 個(gè)進(jìn)程。執(zhí)行命令后,Stress 會(huì)迅速創(chuàng)建 4 個(gè)進(jìn)程,每個(gè)進(jìn)程都全力以赴地計(jì)算隨機(jī)數(shù)的平方根,使得 CPU 使用率急劇上升。此時(shí),我們就像給 CPU 施加了一場(chǎng)高強(qiáng)度的 “體能訓(xùn)練”,讓它在極限狀態(tài)下 “奔跑”。

在另一個(gè)終端中,我們可以使用 top 命令來(lái)實(shí)時(shí)查看系統(tǒng)狀態(tài)。可以看到,系統(tǒng)的平均負(fù)載逐步上升,接近到 4,這表明系統(tǒng)的負(fù)載壓力在不斷增大。同時(shí),有 4 個(gè)進(jìn)程的 CPU 使用率接近 100%,幾乎所有的時(shí)間都在用戶態(tài),整個(gè)系統(tǒng)就像一個(gè)忙碌的蜂巢,每個(gè) “工蜂”(進(jìn)程)都在拼命工作,而 CPU 則是那個(gè)全力協(xié)調(diào)的 “指揮官”,在高負(fù)荷下運(yùn)轉(zhuǎn)。通過(guò)這樣的模擬,我們可以直觀地感受到高 CPU 負(fù)載對(duì)系統(tǒng)的影響,為后續(xù)的性能分析和優(yōu)化提供了真實(shí)的場(chǎng)景依據(jù)。

5.2Sysstat:系統(tǒng)性能的 “監(jiān)控官”

Sysstat 是一個(gè)功能強(qiáng)大的系統(tǒng)性能監(jiān)控工具集,包含了多個(gè)實(shí)用工具,如 mpstat、iostat、sar 等,它們就像一群專業(yè)的 “監(jiān)控官”,從不同角度對(duì)系統(tǒng)性能進(jìn)行全方位的監(jiān)控和分析。

以 mpstat 為例,它主要用于監(jiān)控多處理器系統(tǒng)中每個(gè) CPU 的使用情況,能為我們提供詳細(xì)的 CPU 使用率、中斷次數(shù)、上下文切換等關(guān)鍵指標(biāo)。在終端輸入 “mpstat -P ALL 5” 命令,其中 “-P ALL” 表示監(jiān)控所有 CPU,數(shù)字 “5” 表示每隔 5 秒采樣一次。執(zhí)行命令后,我們會(huì)得到類似如下的輸出:

Linux 4.15.0-109-generic (ubuntu-server)  08/28/2020  _x86_64_ (8 CPU)
11:03:10 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:03:11 PM  all   12.49    0.00    7.10    4.34    0.00    0.29    0.00    0.00    0.00   75.78
11:03:12 PM  all   13.33    0.00    7.67    3.83    0.00    0.17    0.00    0.00    0.00   74.99
Average:     all   12.91    0.00    7.38    4.08    0.00    0.23    0.00    0.00    0.00   75.39

在這些輸出數(shù)據(jù)中,“% usr” 表示用戶空間下的 CPU 使用率,反映了用戶程序在 CPU 上的活動(dòng)時(shí)間;“% sys” 表示系統(tǒng)空間下的 CPU 使用率,體現(xiàn)了內(nèi)核態(tài)程序?qū)?CPU 的占用情況;“% iowait” 表示等待 I/O 操作完成時(shí) CPU 的空閑時(shí)間百分比,若該值較高,可能意味著系統(tǒng)存在 I/O 瓶頸;“% idle” 表示 CPU 的空閑時(shí)間百分比,展示了 CPU 的閑置程度。通過(guò)分析這些數(shù)據(jù),我們能深入了解 CPU 的工作狀態(tài),精準(zhǔn)定位性能問(wèn)題。例如,如果發(fā)現(xiàn)某個(gè) CPU 核心的 “% usr” 使用率持續(xù)過(guò)高,可能是某個(gè)用戶程序存在性能問(wèn)題,需要進(jìn)一步排查和優(yōu)化。

5.3Top:實(shí)時(shí)監(jiān)控的 “儀表盤”

Top 命令是 Linux 系統(tǒng)中最常用的性能分析工具之一,它就像汽車的儀表盤,能夠?qū)崟r(shí)顯示系統(tǒng)中各個(gè)進(jìn)程的資源占用狀況,讓我們對(duì)系統(tǒng)狀態(tài)一目了然。

在終端輸入 “top” 命令后,會(huì)出現(xiàn)一個(gè)動(dòng)態(tài)更新的界面,展示了豐富的系統(tǒng)信息。界面的第一行顯示了系統(tǒng)當(dāng)前時(shí)間、系統(tǒng)運(yùn)行時(shí)長(zhǎng)、當(dāng)前登錄用戶數(shù)以及系統(tǒng)在 1 分鐘、5 分鐘、15 分鐘內(nèi)的平均負(fù)載,就像汽車儀表盤上的時(shí)間、里程和綜合性能指標(biāo)。第二行展示了當(dāng)前進(jìn)程總數(shù)、正在運(yùn)行的進(jìn)程數(shù)、睡眠的進(jìn)程數(shù)、停止的進(jìn)程數(shù)和僵尸進(jìn)程數(shù),讓我們對(duì)系統(tǒng)中的進(jìn)程狀態(tài)有一個(gè)整體的了解。第三行則詳細(xì)列出了 CPU 的使用情況,包括用戶態(tài)(us)、內(nèi)核態(tài)(sy)、改變過(guò)優(yōu)先級(jí)的用戶進(jìn)程(ni)、空閑(id)、I/O 等待(wa)、硬中斷(hi)、軟中斷(si)、虛擬機(jī)(st)等狀態(tài)下的 CPU 使用率,如同儀表盤上各個(gè)性能參數(shù)的詳細(xì)展示。

在實(shí)際使用中,我們可以通過(guò)一些常用參數(shù)來(lái)定制 Top 的顯示內(nèi)容,使其更符合我們的分析需求。比如,按下 “1” 鍵,可以查看每個(gè) CPU 核心的詳細(xì)使用情況,就像切換儀表盤的顯示模式,聚焦到每個(gè)核心的性能表現(xiàn);按下 “P” 鍵,會(huì)按照 CPU 使用率對(duì)進(jìn)程進(jìn)行排序,方便我們快速找到占用 CPU 資源最多的進(jìn)程,就像在儀表盤上突出顯示關(guān)鍵性能指標(biāo)。如果發(fā)現(xiàn)某個(gè)進(jìn)程的 CPU 使用率持續(xù)居高不下,比如某個(gè)大型數(shù)據(jù)庫(kù)查詢進(jìn)程,我們就可以進(jìn)一步分析該進(jìn)程的代碼邏輯、查詢語(yǔ)句等,看是否可以通過(guò)優(yōu)化算法、調(diào)整查詢條件等方式來(lái)降低 CPU 消耗。

Part6.實(shí)戰(zhàn)案例解析

6.1案例一:Java 進(jìn)程 CPU 飆升優(yōu)化

在實(shí)際開(kāi)發(fā)中,我們經(jīng)常會(huì)遇到各種性能問(wèn)題,其中 Java 進(jìn)程 CPU 飆升是一個(gè)較為常見(jiàn)且棘手的問(wèn)題 。下面我們來(lái)看一個(gè)具體的案例 。

最近負(fù)責(zé)的一個(gè)項(xiàng)目上線后,運(yùn)行一段時(shí)間就發(fā)現(xiàn)對(duì)應(yīng)的進(jìn)程竟然占用了 700% 的 CPU,導(dǎo)致公司的物理服務(wù)器都不堪重負(fù),頻繁宕機(jī) 。面對(duì)這類 Java 進(jìn)程 CPU 飆升的問(wèn)題,我們?cè)撊绾味ㄎ唤鉀Q呢?

首先,采用 top 命令定位進(jìn)程 。登錄服務(wù)器,執(zhí)行 top 命令,查看 CPU 占用情況,很快就能發(fā)現(xiàn),PID 為 29706 的 Java 進(jìn)程的 CPU 飆升到 700% 多,且一直降不下來(lái),很顯然出現(xiàn)了問(wèn)題 。

接著,使用 top -Hp 命令定位線程 。使用 top -Hp 命令(其中為 Java 進(jìn)程的 id 號(hào))查看該 Java 進(jìn)程內(nèi)所有線程的資源占用情況(按 shft+p 按照 cpu 占用進(jìn)行排序,按 shift+m 按照內(nèi)存占用進(jìn)行排序) 。在這里,我們很容易發(fā)現(xiàn),多個(gè)線程的 CPU 占用達(dá)到了 90% 多 。我們挑選線程號(hào)為 30309 的線程繼續(xù)分析 。

然后,使用 jstack 命令定位代碼 。先將線程號(hào)轉(zhuǎn)換為 16 進(jìn)制,使用 printf “% x\n” 命令(tid 指線程的 id 號(hào))將 10 進(jìn)制的線程號(hào)轉(zhuǎn)換為 16 進(jìn)制 。轉(zhuǎn)換后的結(jié)果為 7665,由于導(dǎo)出的線程快照中線程的 nid 是 16 進(jìn)制的,而 16 進(jìn)制以 0x 開(kāi)頭,所以對(duì)應(yīng)的 16 進(jìn)制的線程號(hào) nid 為 0x7665 。再采用 jstack 命令導(dǎo)出線程快照,通過(guò)使用 jdk 自帶命令 jstack 獲取該 java 進(jìn)程的線程快照并輸入到文件中 。最后,在生成的文件中根據(jù)線程號(hào) nid 搜索對(duì)應(yīng)的線程描述,判斷應(yīng)該是 ImageConverter.run () 方法中的代碼出現(xiàn)問(wèn)題 。

下面是 ImageConverter.run () 方法中的部分核心代碼 。這段代碼的邏輯是存儲(chǔ)minicap 的 socket 連接返回的數(shù)據(jù),設(shè)置阻塞隊(duì)列長(zhǎng)度,防止出現(xiàn)內(nèi)存溢出 。在 while 循環(huán)中,不斷讀取堵塞隊(duì)列dataQueue 中的數(shù)據(jù),如果數(shù)據(jù)為空,則執(zhí)行 continue 進(jìn)行下一次循環(huán) 。如果不為空,則通過(guò) poll () 方法讀取數(shù)據(jù),做相關(guān)邏輯處理 。初看這段代碼好像沒(méi)什么問(wèn)題,但是如果dataQueue對(duì)象長(zhǎng)期為空的話,這里就會(huì)一直空循環(huán),導(dǎo)致 CPU 飆升 。

// 全局變量
private BlockingQueue<byte[]> dataQueue = new LinkedBlockingQueue<byte[]>(100000);

// 消費(fèi)線程
@Override
public void run() {
    // long start = System.currentTimeMillis();
    while (isRunning) {
        // 分析這里從LinkedBlockingQueue
        if (dataQueue.isEmpty()) {
            continue;
        }
        byte[] buffer = device.getMinicap().dataQueue.poll();
        int len = buffer.length;
    }
}

那么如何解決呢?分析 LinkedBlockingQueue 阻塞隊(duì)列的 API 發(fā)現(xiàn),有兩種取值的 API 。take () 方法取出隊(duì)列中的頭部元素,如果隊(duì)列為空則調(diào)用此方法的線程被阻塞等待,直到有元素能被取出,如果等待過(guò)程被中斷則拋出 InterruptedException;poll () 方法取出隊(duì)列中的頭部元素,如果隊(duì)列為空返回 null 。顯然 take 方法更適合這里的場(chǎng)景 。將代碼修改如下:

while (isRunning) {
    /* if (device.getMinicap().dataQueue.isEmpty()) {
         continue;
     }*/
    byte[] buffer = new byte[0];
    try {
        buffer = device.getMinicap().dataQueue.take();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    ……
}

重啟項(xiàng)目后,測(cè)試發(fā)現(xiàn)項(xiàng)目運(yùn)行穩(wěn)定,對(duì)應(yīng)項(xiàng)目進(jìn)程的 CPU 消耗占比不到 10% 。通過(guò)這個(gè)案例可以看出,在面對(duì) Java 進(jìn)程 CPU 飆升問(wèn)題時(shí),我們可以借助 top、jstack 等工具,逐步定位到問(wèn)題代碼,并通過(guò)合理的代碼修改來(lái)解決問(wèn)題 。

6.2案例二:UV 通道下采樣代碼優(yōu)化

在圖像和視頻處理等領(lǐng)域,常常會(huì)涉及到對(duì)圖像數(shù)據(jù)的各種操作,UV 通道下采樣就是其中常見(jiàn)的一種 。下面我們來(lái)看一個(gè) UV 通道下采樣代碼從標(biāo)量處理轉(zhuǎn)換為向量處理的優(yōu)化案例 。

假設(shè)我們有一個(gè) UV 通道下采樣的任務(wù),輸入是 u8 類型的數(shù)據(jù),通過(guò)鄰近的 4 個(gè)像素求平均,輸出 u8 類型的數(shù)據(jù),達(dá)到 1/4 下采樣的目的 。我們假定每行數(shù)據(jù)長(zhǎng)度是 16 的整數(shù)倍 。最初的 C 代碼實(shí)現(xiàn)如下:

void DownscaleUv(uint8_t *src, uint8_t *dst, int32_t src_stride, int32_t dst_width, int32_t dst_height, int32_t dst_stride) {
    for (int32_t j = 0; j < dst_height; j++) {
        uint8_t *src_ptr0 = src + src_stride * j * 2;
        uint8_t *src_ptr1 = src_ptr0 + src_stride;
        uint8_t *dst_ptr = dst + dst_stride * j;
        for (int32_t i = 0; i < dst_width; i += 2) {
            // U通道
            dst_ptr[i] = (src_ptr0[i * 2] + src_ptr0[i * 2 + 2] +
                          src_ptr1[i * 2] + src_ptr1[i * 2 + 2]) / 4;
            // V通道
            dst_ptr[i + 1] = (src_ptr0[i * 2 + 1] + src_ptr0[i * 2 + 3] +
                              src_ptr1[i * 2 + 1] + src_ptr1[i * 2 + 3]) / 4;
        }
    }
}

為了提升代碼性能,我們可以將其轉(zhuǎn)換為向量處理,利用 NEON 指令集進(jìn)行優(yōu)化 。具體步驟如下:

①內(nèi)層循環(huán)向量化

內(nèi)層循環(huán)是代碼執(zhí)行次數(shù)最多的部分,因此是向量化的重點(diǎn) 。由于我們的輸入和輸出都是 u8 類型,NEON 寄存器 128bit,所以每次可以處理 16 個(gè)數(shù)據(jù) 。修改后的內(nèi)層循環(huán)代碼如下:

// 每次有16個(gè)數(shù)據(jù)輸出
for (i = 0; i < dst_width; i += 16) {
    //數(shù)據(jù)處理部分......
}

②數(shù)據(jù)類型和指令選擇

輸入數(shù)據(jù)加載時(shí),UV 通道的數(shù)據(jù)是交織的,使用 vld2 指令可以實(shí)現(xiàn)解交織 。在數(shù)據(jù)處理過(guò)程中,選擇合適的指令進(jìn)行計(jì)算 。例如,水平兩個(gè)數(shù)據(jù)相加可以使用 vpaddlq_u8 指令,上下兩個(gè)數(shù)據(jù)相加之后求均值可以使用 vshrn_n_u16 和 vaddq_u16 指令 。

③代碼實(shí)現(xiàn)

#include <arm_neon.h>

void DownscaleUvNeon(uint8_t *src, uint8_t *dst, int32_t src_width, int32_t src_stride, int32_t dst_width, int32_t dst_height, int32_t dst_stride) {
    //load偶數(shù)行的源數(shù)據(jù),2組每組16個(gè)u8類型數(shù)據(jù)
    uint8x16x2_t v8_src0;
    //load奇數(shù)行的源數(shù)據(jù),需要兩個(gè)Q寄存器
    uint8x16x2_t v8_src1;
    //目的數(shù)據(jù)變量,需要一個(gè)Q寄存器
    uint8x8x2_t v8_dst;
    //目前只處理16整數(shù)倍部分的結(jié)果
    int32_t dst_width_align = dst_width & (-16);
    //向量化剩余的部分需要單獨(dú)處理
    int32_t remain = dst_width & 15;
    int32_t i = 0;
    //外層高度循環(huán),逐行處理
    for (int32_t j = 0; j < dst_height; j++) {
        //偶數(shù)行源數(shù)據(jù)指針
        uint8_t *src_ptr0 = src + src_stride * j * 2;
        //奇數(shù)行源數(shù)據(jù)指針
        uint8_t *src_ptr1 = src_ptr0 + src_stride;
        //目的數(shù)據(jù)指針
        uint8_t *dst_ptr = dst + dst_stride * j;
        //內(nèi)層循環(huán),一次16個(gè)u8結(jié)果輸出
        for (i = 0; i < dst_width_align; i += 16) {
            //提取數(shù)據(jù),進(jìn)行UV分離
            v8_src0 = vld2q_u8(src_ptr0);
            src_ptr0 += 32;
            v8_src1 = vld2q_u8(src_ptr1);
            src_ptr1 += 32;
            //水平兩個(gè)數(shù)據(jù)相加
            uint16x8_t v16_u_sum0 = vpaddlq_u8(v8_src0.val[0]);
            uint16x8_t v16_v_sum0 = vpaddlq_u8(v8_src0.val[1]);
            uint16x8_t v16_u_sum1 = vpaddlq_u8(v8_src1.val[0]);
            uint16x8_t v16_v_sum1 = vpaddlq_u8(v8_src1.val[1]);
            //上下兩個(gè)數(shù)據(jù)相加,之后求均值
            v8_dst.val[0] = vshrn_n_u16(vaddq_u16(v16_u_sum0, v16_u_sum1), 2);
            v8_dst.val[1] = vshrn_n_u16(vaddq_u16(v16_v_sum0, v16_v_sum1), 2);
            //UV通道結(jié)果交織存儲(chǔ)
            vst2_u8(dst_ptr, v8_dst);
            dst_ptr += 16;
        }
        //process leftovers......
    }
}

通過(guò)這樣的優(yōu)化,將原本的標(biāo)量處理轉(zhuǎn)換為向量處理,充分利用了 NEON 指令集的并行處理能力,大大提升了 UV 通道下采樣的效率 。在實(shí)際應(yīng)用中,對(duì)于圖像和視頻處理等對(duì)性能要求較高的場(chǎng)景,這種基于向量處理的優(yōu)化方式能夠顯著提高程序的運(yùn)行速度,為用戶帶來(lái)更好的體驗(yàn) 。

責(zé)任編輯:武曉燕 來(lái)源: 深度Linux
相關(guān)推薦

2018-04-04 13:44:59

數(shù)據(jù)庫(kù)MySQL延遲

2019-12-10 08:10:35

LinuxCPU性能優(yōu)化

2010-04-08 09:05:08

2009-06-15 09:47:12

Java程序內(nèi)存溢出

2023-11-01 11:51:08

Linux性能優(yōu)化

2020-07-25 09:33:42

智能手機(jī)文件

2010-12-22 13:09:23

Linux性能監(jiān)測(cè)CPU

2010-06-04 09:42:47

Linux 測(cè)試cpu

2020-05-26 12:52:06

Windows 10網(wǎng)絡(luò)故障

2025-02-04 10:58:16

2023-02-02 08:04:15

Ceph數(shù)據(jù)CPU

2022-06-28 16:00:17

Linux網(wǎng)絡(luò)性能優(yōu)化

2022-05-05 09:27:31

Linux服務(wù)器優(yōu)化

2025-05-19 09:10:16

2022-07-15 08:52:03

Linux優(yōu)化

2010-01-28 09:55:05

性能優(yōu)化

2019-07-26 06:30:37

CPU代碼操作系統(tǒng)

2025-05-08 09:11:41

2010-05-26 18:08:30

Linux性能監(jiān)控
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)