“不服跑個(gè)分?” 是噱頭還是實(shí)力?
時(shí)間:2021-09-10 16:33:31
手機(jī)看文章
掃描二維碼
隨時(shí)隨地手機(jī)看文章
[導(dǎo)讀]一、背景:性能之戰(zhàn)“不服跑個(gè)分”已經(jīng)淪為手機(jī)行業(yè)的調(diào)侃用語(yǔ),但是實(shí)話實(shí)說(shuō),在操作系統(tǒng)領(lǐng)域“跑分”確實(shí)是最重要的評(píng)價(jià)方式之一。比如Linux內(nèi)核社區(qū)常常以跑分軟件得分,來(lái)評(píng)價(jià)一個(gè)優(yōu)化補(bǔ)丁的價(jià)值。甚至還有phoronix這樣專注于Linux跑分的媒體。而且今天我還想說(shuō)一點(diǎn),讓軟件跑分...
一、背景:性能之戰(zhàn)
“不服跑個(gè)分”已經(jīng)淪為手機(jī)行業(yè)的調(diào)侃用語(yǔ),但是實(shí)話實(shí)說(shuō),在操作系統(tǒng)領(lǐng)域“跑分”確實(shí)是最重要的評(píng)價(jià)方式之一。比如 Linux 內(nèi)核社區(qū)常常以跑分軟件得分,來(lái)評(píng)價(jià)一個(gè)優(yōu)化補(bǔ)丁的價(jià)值。甚至還有 phoronix 這樣專注于 Linux 跑分的媒體。而且今天我還想說(shuō)一點(diǎn),讓軟件跑分高,這是實(shí)力的體現(xiàn),是建立在對(duì)內(nèi)核的深刻理解基礎(chǔ)上的。本文的故事就源于一次日常的性能優(yōu)化分析。我們?cè)谠u(píng)估自動(dòng)化性能調(diào)優(yōu)軟件 tuned 的時(shí)候,發(fā)現(xiàn)它在服務(wù)器場(chǎng)景,對(duì) Linux 內(nèi)核調(diào)度器相關(guān)的參數(shù)做了一些微小的修改,但是這些修改卻很大程度改善了 hackbench 這款跑分軟件的性能。是不是很有意思?讓我們一起來(lái)一探究竟。本文將從幾個(gè)方面展開(kāi),并重點(diǎn)介紹黑體字部分:- 相關(guān)知識(shí)簡(jiǎn)介
- hackbench 工作模式簡(jiǎn)介
- hackbench 性能受損之源
- 雙參數(shù)優(yōu)化
- 思考與拓展
二、相關(guān)知識(shí)簡(jiǎn)介
2.1 CFS調(diào)度器
Linux 中大部分(可以粗略認(rèn)為是實(shí)時(shí)任務(wù)之外的所有)線程/進(jìn)程,都由一個(gè)叫 CFS(完全公平調(diào)度器)的調(diào)度器進(jìn)行調(diào)度,它是 Linux 最核心的組件之一。(在Linux中,線程和進(jìn)程只有細(xì)微差別,下文統(tǒng)一用進(jìn)程表述)CFS 的核心是紅黑樹(shù),用于管理系統(tǒng)中進(jìn)程的運(yùn)行時(shí)間,作為選擇下一個(gè)將要運(yùn)行的進(jìn)程的依據(jù)。此外,它還支持優(yōu)先級(jí)、組調(diào)度(基于我們熟知的 cgroup 實(shí)現(xiàn))、限流等功能,滿足各種高級(jí)需求。CFS 的詳細(xì)介紹。2.2 hackbench
hackbench 是一個(gè)針對(duì) Linux 內(nèi)核調(diào)度器的壓力測(cè)試工具,它的主要工作是創(chuàng)建指定數(shù)量的調(diào)度實(shí)體對(duì)(線程/進(jìn)程),并讓它們通過(guò) sockets/pipe 進(jìn)行數(shù)據(jù)傳輸,最后統(tǒng)計(jì)整個(gè)運(yùn)行過(guò)程的時(shí)間開(kāi)銷。2.3 CFS 調(diào)度器參數(shù)
本文重點(diǎn)關(guān)注以下兩個(gè)參數(shù),這兩個(gè)參數(shù)也是影響 hackbench 跑分性能的重要因素。系統(tǒng)管理員可以使用 sysctl 命令來(lái)進(jìn)行設(shè)置。- 最小粒度時(shí)間:kernel.sched_min_granularity_ns? ??
如圖 1 所示,每個(gè)進(jìn)程都能夠在 CPU 上運(yùn)行且時(shí)間各有長(zhǎng)短,sched_min_granularity_ns 保證了每個(gè)進(jìn)程的最小運(yùn)行時(shí)間(優(yōu)先級(jí)相同的情況下),sched_min_granularity_ns 越大每個(gè)進(jìn)程單次可運(yùn)行的時(shí)間就越長(zhǎng)。圖 1:sched_min_granularity_ns 示意圖
- 喚醒搶占粒度:kernel.sched_wakeup_granularity_ns
? ? ? ? 如圖 2 所示,有 process-{1,2,3} 三個(gè)進(jìn)程被喚醒,因?yàn)?process-3 的運(yùn)行時(shí)間大于 curr(正在 CPU 上運(yùn)行的進(jìn)程)無(wú)法搶占運(yùn)行,而 process-2 運(yùn)行時(shí)間小于 curr 但其差值小于 sched_wakeup_granularity_ns 也無(wú)法搶占運(yùn)行,只有 process-1 能夠搶占 curr 運(yùn)行,因此 sched_wakeup_granularity_ns 越小,進(jìn)程被喚醒后的響應(yīng)時(shí)間就越快(等待運(yùn)行時(shí)間越短)。圖 2:sched_wakeup_granularity_ns 示意圖三、hackbench 工作模式簡(jiǎn)介
hackbench 工作模式分為 process mode 和 thread mode,主要區(qū)別就是以創(chuàng)建 process 還是 thread 為基礎(chǔ)來(lái)進(jìn)行測(cè)試,下面以 thread 來(lái)進(jìn)行介紹。
- hackbench 會(huì)創(chuàng)建若干線程(偶數(shù)),均分為兩類線程:sender 和 receiver
- 并將其劃分為 n 個(gè) group,每個(gè) group 包含 m ?對(duì) sender 和 receiver。
- 每個(gè) sender 的任務(wù)就是給其所在 group 的所有 receiver 輪流發(fā)送 loop 次大小為 datasize 的數(shù)據(jù)包
- receiver 則只負(fù)責(zé)接收數(shù)據(jù)包即可。
- 同一個(gè) group 中的sender 和 receiver 有兩種方式進(jìn)行通信:pipe 和 local socket(一次測(cè)試中只能都是 pipe 或者 socket),不同 group 之間的線程沒(méi)有交互關(guān)系。
- 對(duì)于 receiver,當(dāng) buffer 中沒(méi)有數(shù)據(jù)時(shí),receiver 會(huì)被阻塞并主動(dòng)讓出 CPU 進(jìn)入睡眠。
- 對(duì)于 sender,如果 buffer 中沒(méi)有足夠空間寫(xiě)入數(shù)據(jù)時(shí), sender 也會(huì)被阻塞且主動(dòng)讓出 CPU。
四、hackbench性能影響之源
在hackbench-socket 測(cè)試中,tuned修改了 CFS 的 sched_min_granularity_ns 和 sched_wakeup_granularity_ns 兩個(gè)參數(shù),導(dǎo)致了性能的顯著區(qū)別。具體如下:開(kāi)關(guān)/參數(shù)和性能 | sched_min_granularity_ns | sched_wakeup_granularity_ns | 性能 |
關(guān) tuned | 2.25ms | 3ms | 差 |
開(kāi) tuned | 10ms | 15ms | 好 |
五、雙參數(shù)優(yōu)化
注:為了簡(jiǎn)介表達(dá)下面會(huì)以 m 表示 kernel.sched_min_granularity_ns,w 表示 kernel.sched_wakeup_granularity_ns為了探索雙參數(shù)對(duì)于調(diào)度器的影響,我們選擇每次固定一個(gè)參數(shù),研究另一個(gè)參數(shù)變化對(duì)于性能的影響,并使用系統(tǒng)知識(shí)來(lái)解釋這種現(xiàn)象背后的原理。5.1 固定?sched_wakeup_granularity_ns
圖 4: 固定 w,調(diào)整m在上圖中我們固定了參數(shù) w 并根據(jù)參數(shù) m 變化趨勢(shì)其劃分為三個(gè)部分:區(qū)域A(1ms~4ms),區(qū)域B(4ms~17ms),區(qū)域C(17ms~30ms)。在區(qū)域A中四條曲線均呈現(xiàn)一個(gè)極速下降的趨勢(shì),而在區(qū)域B中四條曲線都處于一種震蕩狀態(tài),波動(dòng)較大,最后在區(qū)域C中四條曲線都趨于穩(wěn)定。在第二節(jié)相關(guān)知識(shí)中可以知道 m 影響著進(jìn)程的運(yùn)行時(shí)間,同時(shí)也意味著它影響著進(jìn)程的“被動(dòng)上下文切換”。- 對(duì)于區(qū)域A而言,搶占過(guò)于頻繁,而大部分搶占都是無(wú)意義的,因?yàn)閷?duì)端無(wú)數(shù)據(jù)可寫(xiě)/無(wú)緩沖區(qū)可用,導(dǎo)致大量冗余的“主動(dòng)上下文切換“。此時(shí)較大的 w 能讓 sender/receiver 有更多的時(shí)間來(lái)寫(xiě)入數(shù)據(jù)/消耗數(shù)據(jù)來(lái)減少對(duì)端進(jìn)程無(wú)意義的“主動(dòng)上下文切換“。
- 對(duì)于區(qū)域B而言,隨著 m 的增加漸漸滿足 sender/receiver 執(zhí)行任務(wù)的時(shí)間需求能夠在緩沖區(qū)寫(xiě)入/讀出足夠的數(shù)據(jù),因此需要較小的 w 來(lái)增加喚醒進(jìn)程的搶占幾率,讓對(duì)端進(jìn)程能夠更快的響應(yīng)處理數(shù)據(jù),減少下一輪調(diào)度時(shí)的“主動(dòng)上下文切換”。
- 對(duì)于區(qū)域C而言,m已經(jīng)足夠大,已經(jīng)幾乎不會(huì)有“被動(dòng)上下文切換”發(fā)生,進(jìn)程會(huì)在執(zhí)行完任務(wù)之后進(jìn)行“主動(dòng)上下文切換”等待對(duì)端進(jìn)程進(jìn)行處理,此時(shí) m 對(duì)性能的影響就很小了。
5.2 固定?sched_min_granularity_ns
圖 5: 固定 m,調(diào)整w在上圖中我們固定了參數(shù) m,同樣劃分了三個(gè)區(qū)域:- 在區(qū)域A中,同樣存在圖 4 中的現(xiàn)象,較大 m 受 w 的影響較小,而較小的 m 隨著 w 的增大性能會(huì)越來(lái)越好。
- 在區(qū)域B中,中等大小的 m(8ms/12ms)進(jìn)程還是存在較多“被動(dòng)上下文切換”,并且其中的進(jìn)程已經(jīng)處理了相當(dāng)一部分?jǐn)?shù)據(jù)期望對(duì)端進(jìn)程能夠盡快的響應(yīng)處理,因此較大 w 會(huì)嚴(yán)重影響中等大小 m 的性能。
- 在區(qū)域C中圖5和圖4表現(xiàn)一致都是趨于穩(wěn)定,因?yàn)?w 過(guò)大時(shí)幾乎不會(huì)發(fā)生喚醒搶占,因此這時(shí)單純 w 值的變化對(duì)性能的影響并不大,但是過(guò)大的 w 對(duì)于中等大小的 m 則會(huì)造成性能問(wèn)題(原因同上條)。
5.3 性能趨勢(shì)總覽
下面是一個(gè)實(shí)驗(yàn)數(shù)據(jù)的熱力總覽圖,來(lái)直觀展示 m 和 w 之間的制約關(guān)系,以供需要的同學(xué)參考分析。三個(gè)區(qū)域和圖 4、圖 5 的區(qū)域會(huì)略有不同。圖 6:總覽圖5.4 最優(yōu)雙參數(shù)(對(duì)于 hackbench )
- 從上面兩節(jié)的分析可知對(duì)于 hackbench 這樣帶有“主動(dòng)上下文切換”的場(chǎng)景可以選擇較大的 m(例如:15~20ms)。
- 在pipe/socket 雙向通信的場(chǎng)景中,對(duì)端的響應(yīng)時(shí)間會(huì)對(duì)影響進(jìn)程的下一次處理,為了讓對(duì)端進(jìn)程能夠及時(shí)響應(yīng)可以選擇一個(gè)中等大小的 w(例如:6~8ms)來(lái)獲取較高的性能。
六、思考與擴(kuò)展
- 在桌面場(chǎng)景中,應(yīng)用更偏向于交互型,應(yīng)用的服務(wù)質(zhì)量也更多的體現(xiàn)在應(yīng)用對(duì)于用戶操作的響應(yīng)時(shí)間,因此可以選擇較小的 sched_wakeup_granularity_ns 來(lái)提高應(yīng)用的交互性。
- 在服務(wù)器場(chǎng)景中,應(yīng)用更偏向于計(jì)算處理,應(yīng)用需要更多的運(yùn)行時(shí)間來(lái)進(jìn)行密集計(jì)算,因此可以選擇較大的 sched_min_granularity_ns,但是為了防止單個(gè)進(jìn)程獨(dú)占 CPU 過(guò)久同時(shí)也為了能夠及時(shí)處理客戶端請(qǐng)求響應(yīng),應(yīng)該選擇一個(gè)中等大小的 sched_wakeup_granularity_ns。
- 在 Linux 原生內(nèi)核中 m 和 w 的默認(rèn)參數(shù)被設(shè)置為適配桌面場(chǎng)景,Anolis OS的用戶,需要根據(jù)自己部署的應(yīng)用的場(chǎng)景,屬于桌面型還是服務(wù)器型,來(lái)選擇內(nèi)核參數(shù),或者使用tuned的推薦配置。而 hackbench 作為一個(gè)介于桌面和服務(wù)器間的應(yīng)用,也可以作為配置的參考。
參考資料
- phoronix:https://www.phoronix.com/
- 自動(dòng)化性能調(diào)優(yōu)軟件tuned:https://developer.aliyun.com/article/86750
- CFS 的詳細(xì)介紹:?http://www.wowotech.net/process_management/451.html
- 在 Linux 原生內(nèi)核中 m 和 w 的默認(rèn)參數(shù)被設(shè)置為適配桌面場(chǎng)景:https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt