深入剖析 CPU、內(nèi)存與 I/O 瓶頸
今天我們開(kāi)始學(xué)習(xí)《性能優(yōu)化》專欄的第02章:深入剖析 CPU、內(nèi)存與 I/O 瓶頸。
在計(jì)算機(jī)系統(tǒng)里,各個(gè)組件的運(yùn)行速度參差不齊,當(dāng)計(jì)算機(jī)系統(tǒng)的短板存在時(shí),往往會(huì)導(dǎo)致性能瓶頸。例如,CPU 負(fù)載過(guò)高時(shí),任務(wù)就會(huì)排隊(duì),進(jìn)而延遲執(zhí)行。而在大多數(shù)情況下,CPU、內(nèi)存和 I/O 這三大組件是系統(tǒng)最容易成為瓶頸的部分。接下來(lái),我們就一起從CPU、內(nèi)存與IO角度深入分析系統(tǒng)的性能瓶頸。
CPU 性能
作為計(jì)算機(jī)最重要的計(jì)算單元,中央處理器(CPU)在系統(tǒng)中的作用是非常重要的。評(píng)估 CPU 性能時(shí),通常通過(guò)以下幾種方法:
Top命令查看CPU性能
通過(guò) top
命令可以實(shí)時(shí)查看 CPU 的使用情況,按 1 鍵后,我們可以看到每個(gè) CPU 核心的運(yùn)行情況。
核心指標(biāo)包括:
us
:用戶態(tài)所占的 CPU 百分比,表示應(yīng)用程序占用的 CPU 時(shí)間。sy
:內(nèi)核態(tài)所占的 CPU 百分比,表示操作系統(tǒng)內(nèi)核執(zhí)行的任務(wù)所占的 CPU 時(shí)間。ni
:高優(yōu)先級(jí)應(yīng)用所占的 CPU 百分比。wa
:等待 I/O 設(shè)備所占的 CPU 百分比,過(guò)高的wa
值通常意味著 I/O 設(shè)備存在瓶頸。hi
:硬中斷占用的 CPU 百分比。si
:軟中斷占用的 CPU 百分比。st
:表示虛擬機(jī)對(duì)宿主機(jī)的影響。id
:空閑 CPU 百分比,反映了 CPU 的使用情況。
負(fù)載分析任務(wù)排隊(duì)
通過(guò) uptime
命令可以查看系統(tǒng)的負(fù)載情況,負(fù)載反映了系統(tǒng)任務(wù)的排隊(duì)情況,例如,使用uptime命令可以顯示最近1min、5min和15min的數(shù)據(jù)。
通過(guò)反復(fù)測(cè)試,可以得出如下結(jié)論:
- 單核負(fù)載為 1 表示 CPU 剛好達(dá)到極限。
- 雙核負(fù)載為 2 表示每個(gè)核心的負(fù)載都接近極限。
- 在多核系統(tǒng)中,負(fù)載值達(dá)到核數(shù)時(shí),系統(tǒng)仍能正常工作,但如果超出核數(shù),任務(wù)開(kāi)始排隊(duì),系統(tǒng)性能就會(huì)下降。
vmstat 命令查看CPU繁忙程度
vmstat
命令可以幫助我們了解 CPU 的繁忙程度。
需要特別注意以下幾個(gè)關(guān)鍵指標(biāo):
b
:表示阻塞的進(jìn)程,如果系統(tǒng)有負(fù)載問(wèn)題,可以關(guān)注下這個(gè)指標(biāo),通常意味著有大量的 I/O 操作。si/so
:表示交換區(qū)(Swap)的使用情況,過(guò)多的交換操作會(huì)嚴(yán)重影響性能。cs
:表示每分鐘上下文切換次數(shù),頻繁的上下文切換會(huì)降低系統(tǒng)性能,需要考慮進(jìn)程或者線程是否開(kāi)啟的過(guò)多。
內(nèi)存性能
內(nèi)存對(duì)于系統(tǒng)性能的影響同樣不可忽視,尤其是在程序運(yùn)行過(guò)程中,內(nèi)存的管理和分配直接影響著系統(tǒng)的響應(yīng)速度和穩(wěn)定性。
操作系統(tǒng)通常會(huì)將邏輯內(nèi)存映射到物理內(nèi)存和虛擬內(nèi)存中,系統(tǒng)可用的內(nèi)存是物理內(nèi)存與虛擬內(nèi)存之和。
top 命令內(nèi)存監(jiān)控
在 top
命令的輸出中,我們通常關(guān)注以下幾個(gè)字段:
VIRT
:虛擬內(nèi)存總量,通常較大,但不需要過(guò)多關(guān)注。RES
:實(shí)際占用的內(nèi)存,反映了進(jìn)程真正使用的內(nèi)存量。SHR
:共享內(nèi)存,通常為可以被多個(gè)進(jìn)程共享的內(nèi)存區(qū)域。
CPU 緩存
CPU 與內(nèi)存之間存在巨大的速度差異,因此設(shè)計(jì)了多級(jí)緩存來(lái)加速數(shù)據(jù)的訪問(wèn)。不同的 CPU 核心通常會(huì)有不同層次的緩存(如 L1、L2、L3 緩存)。
在并發(fā)編程中,涉及 CPU 緩存的常見(jiàn)問(wèn)題之一是“偽共享”。偽共享指的是在這些高速緩存中,以緩存行為單位進(jìn)行存儲(chǔ),即使修改緩存行中一個(gè)非常小的數(shù)據(jù),都會(huì)刷新整個(gè)緩存行。所以,當(dāng)多線程修改一些變量的值時(shí),如果這些變量都在同一個(gè)緩存行里,就會(huì)造成頻繁刷新,影響彼此的性能。
HugePage
在CPU與內(nèi)存的整體架構(gòu)上,存在一個(gè)TLB組件。
這個(gè)TLB組件速度很快,但容量非常有限,在普通機(jī)器上沒(méi)有性能瓶頸。如果機(jī)器配置比較高,物理內(nèi)存比較大,就會(huì)產(chǎn)生非常多的映射表,降低CPU的檢索性能。
在大內(nèi)存機(jī)器上,為了提高 CPU 對(duì)大內(nèi)存的訪問(wèn)效率,通常會(huì)采用較大的頁(yè)(HugePage),這有助于減少映射表的數(shù)量,提高內(nèi)存管理的效率。
需要注意的是:開(kāi)啟 HugePage 可能會(huì)導(dǎo)致內(nèi)存競(jìng)爭(zhēng)的加劇,因此需要根據(jù)實(shí)際情況進(jìn)行調(diào)整。
提前分配內(nèi)存
對(duì)于Java來(lái)說(shuō),可以在程序啟動(dòng)的時(shí)候就將內(nèi)存分配好。例如,配置了JVM的Xms、Xmx和Xmn等參數(shù),指定堆的初始化大小、最大大小等,但是默認(rèn)是在程序真正使用時(shí),才會(huì)分配內(nèi)存。如果在啟動(dòng)時(shí)加上-XX:+AlwaysPreTouch
參數(shù),JVM在啟動(dòng)時(shí)就會(huì)分配好內(nèi)存。程序雖然啟動(dòng)變慢,但會(huì)提高運(yùn)行時(shí)的性能。
I/O 性能
I/O 設(shè)備是計(jì)算機(jī)中最慢的部分,尤其是硬盤,其讀寫速度遠(yuǎn)低于 CPU 和內(nèi)存的速度。為了提高 I/O 性能,我們通常需要采取一些手段進(jìn)行優(yōu)化。
iostat 命監(jiān)控磁盤 I/O
最能體現(xiàn) I/O 繁忙程度的,就是 top 命令和 vmstat 命令中的 wa%。如果程序正在輸出大量的日志,I/O wait 就可能非常高。
top命令執(zhí)行結(jié)果如下:
iostat命令一般可以通過(guò)sysstat包進(jìn)行安裝,在命令行執(zhí)行iostat -x 1 3
執(zhí)行結(jié)果如下:
關(guān)鍵指標(biāo)包括:
%util
:表示磁盤的使用率,通常超過(guò) 80% 表示磁盤負(fù)載很高。avgqu-sz
:表示平均請(qǐng)求隊(duì)列長(zhǎng)度,越小越好。await
:表示磁盤請(qǐng)求的平均響應(yīng)時(shí)間,通常應(yīng)小于 5ms。svctm
:表示每次 I/O 操作的平均服務(wù)時(shí)間,與await
密切相關(guān)。
零拷貝技術(shù)
硬盤上的數(shù)據(jù),在發(fā)往網(wǎng)絡(luò)之前,需要經(jīng)過(guò)多次緩沖區(qū)的拷貝,以及用戶空間和內(nèi)核空間的多次切換。如果能減少一些拷貝的過(guò)程,效率就能提升,所以零拷貝應(yīng)運(yùn)而生。
零拷貝是一種非常重要的性能優(yōu)化手段,比如常見(jiàn)的 Kafka、Nginx 等,就使用了這種技術(shù)。
無(wú)零拷貝流程
如果沒(méi)有零拷貝技術(shù),想要將一個(gè)文件通過(guò)Socket發(fā)送出去,整體流程如下圖所示。
整體流程如下:
(1)將文件內(nèi)容拷貝到內(nèi)核緩沖區(qū)。
(2)將內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到用戶空間內(nèi)存。
(3)將用戶空間內(nèi)存中的數(shù)據(jù)寫入到內(nèi)核緩沖區(qū)。
(4)Socket讀取內(nèi)核緩沖區(qū)的數(shù)據(jù)并發(fā)送。
零拷貝流程
這里以sendfile為例,零拷貝流程如下圖所示。
采用零拷貝技術(shù)后,少了一個(gè)步驟,那就是內(nèi)核緩存不再向用戶空間拷貝數(shù)據(jù),不僅節(jié)省了內(nèi)存空間,也節(jié)省了CPU的調(diào)度時(shí)間,讓整體效率更加高效。
本章總結(jié)
本章主要深入探討了影響計(jì)算機(jī)性能的三個(gè)關(guān)鍵組件:CPU、內(nèi)存和 I/O。通過(guò)命令行工具(如 top
、vmstat
、iostat
等),可以監(jiān)控這些組件的性能,從而發(fā)現(xiàn)潛在的瓶頸。然而,單純的監(jiān)控只能幫助我們大致判斷性能問(wèn)題的位置,若要精確定位性能瓶頸,還需進(jìn)行更深入的分析與排查。
希望本章的內(nèi)容能夠讓大家真正學(xué)到有用的知識(shí),我們一起努力徹底吃透性能優(yōu)化技術(shù)。