Linux调度系统全景指南(终结篇)
點(diǎn)擊上方藍(lán)字關(guān)注公眾號(hào),更多經(jīng)典內(nèi)容等著你
? ?
?
| 導(dǎo)語本文主要是講Linux的調(diào)度系統(tǒng), 本篇是終結(jié)篇,主要講當(dāng)前多核系統(tǒng)調(diào)度策略和調(diào)度優(yōu)化,調(diào)度可以說是操作系統(tǒng)的靈魂,為了讓CPU資源利用最大化,Linux設(shè)計(jì)了一套非常精細(xì)的調(diào)度系統(tǒng),對(duì)大多數(shù)場(chǎng)景都進(jìn)行了很多優(yōu)化,系統(tǒng)擴(kuò)展性強(qiáng),我們可以根據(jù)業(yè)務(wù)模型和業(yè)務(wù)場(chǎng)景的特點(diǎn),有針對(duì)性的去進(jìn)行性能優(yōu)化。歡迎大家相互交流學(xué)習(xí)!
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 目錄
上篇請(qǐng)看(CPU和中斷):Linux調(diào)度系統(tǒng)全景指南(上篇)
中篇請(qǐng)看(搶占和時(shí)鐘):Linux調(diào)度系統(tǒng)全景指南(中篇)
下篇請(qǐng)看(進(jìn)程和線程):Linux調(diào)度系統(tǒng)全景指南(下篇)? ?? ? ?? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?多核調(diào)度
在單核系統(tǒng)中,調(diào)度器只需要考慮任務(wù)執(zhí)行先后順序的問題,在多核系統(tǒng)中,除了任務(wù)先后問題,調(diào)度器還需要考慮CPU分配問題。也就是說,在多核系統(tǒng)中,調(diào)度器還需要決定任務(wù)在哪個(gè)CPU上運(yùn)行,需要盡量做到公平和整體性能最大化。一般來說,調(diào)度器可以被劃分為以下幾類:
(1)全局類(Global):即一個(gè)調(diào)度器就可以管理系統(tǒng)中的所有CPU,任務(wù)可以在CPU之間自由遷移。
(2)集群類(Clustered):系統(tǒng)中的CPU被分成互不相交的幾個(gè)cluster,調(diào)度器負(fù)責(zé)調(diào)度任務(wù)到cluster內(nèi)的CPU上去。
(3)分區(qū)類(Partitioned ):每個(gè)調(diào)度器只管自己的那個(gè)CPU,系統(tǒng)有多少個(gè)CPU就有多少個(gè)調(diào)度器實(shí)體。
(4)任意類(Arbitrary ):每一個(gè)任務(wù)都可以運(yùn)行在任何一個(gè)CPU集合上。
?
內(nèi)核調(diào)度系統(tǒng)針對(duì)CPU架構(gòu)演進(jìn):單CPU->SMP->NUMA->復(fù)雜混合架構(gòu), 做了針對(duì)性的優(yōu)化設(shè)計(jì);
SMP
? ? ? ?
SMP (Symmetric Multiprocessing),對(duì)稱多處理器. 顧名思義, 在SMP中所有的處理器都是對(duì)等的, 它們通過總線連接共享同一塊物理內(nèi)存,這也就導(dǎo)致了系統(tǒng)中所有資源(CPU、內(nèi)存、I/O等)都是共享的,其架構(gòu)簡(jiǎn)單,但是拓展性能比較差。
多處理器系統(tǒng)上,內(nèi)核必須考慮幾個(gè)額外的問題,以確保良好的調(diào)度效率。
?CPU負(fù)荷必須盡可能公平地在所有的處理器上共享。如果一個(gè)處理器負(fù)責(zé)3個(gè)并發(fā)的應(yīng)用程序,而另一個(gè)只能處理空閑進(jìn)程,那是沒有意義的。
進(jìn)程與系統(tǒng)中某些處理器的親合性(affinity)必須是可設(shè)置的。例如在4個(gè)CPU系統(tǒng)中,可以將計(jì)算密集型應(yīng)用程序綁定到前3個(gè)CPU,而剩余的(交互式)進(jìn)程則在第4個(gè)CPU上運(yùn)行。
內(nèi)核必須能夠?qū)⑦M(jìn)程從一個(gè)CPU遷移到另一個(gè)。但該選項(xiàng)必須謹(jǐn)慎使用,因?yàn)樗鼤?huì)嚴(yán)重危害性能。在小型SMP系統(tǒng)上CPU高速緩存是最大的問題。對(duì)于真正大型系統(tǒng), CPU與遷移進(jìn)程此前使用的物理內(nèi)存距離可能有若干米,因此對(duì)該進(jìn)程內(nèi)存的訪問代價(jià)高昂。
進(jìn)程對(duì)特定CPU的親合性 ,定義在task_struct的 cpus_allowed 成 員 中 。Linux 提供了sched_setaffinity系統(tǒng)調(diào)用,可修改進(jìn)程與CPU的現(xiàn)有分配關(guān)系
在SMP系統(tǒng)上,每個(gè)調(diào)度器類的調(diào)度方法必須增加兩個(gè)額外的函數(shù):
load_balance:允許從最忙的就緒隊(duì)列分配多個(gè)進(jìn)程到當(dāng)前CPU,但移動(dòng)的負(fù)荷不能比max_load_move更多,每當(dāng)內(nèi)核認(rèn)為有必要重新均衡時(shí),核心調(diào)度器代碼都會(huì)調(diào)用這些函數(shù);
move_one_task:move_one_task則使用了iter_move_one_task,從最忙碌的就緒隊(duì)列移出一個(gè)進(jìn)程,遷移到當(dāng)前CPU的就緒隊(duì)列;
在SMP系統(tǒng)上,周期性調(diào)度器函數(shù)scheduler_tick按上文所述完成所有系統(tǒng)都需要的任務(wù)之后,會(huì)調(diào)用trigger_load_balance函數(shù),這會(huì)引發(fā)
SCHEDULE_SOFTIRQ軟中斷softIRQ,該中斷確保會(huì)在適當(dāng)?shù)臅r(shí)機(jī)執(zhí)行run_rebalance_domains。該函數(shù)最終對(duì)當(dāng)前CPU調(diào)用rebalance_domains,實(shí)現(xiàn)負(fù)載均衡。
?
NUMA
? ? ? ??
非統(tǒng)一內(nèi)存訪問架構(gòu)(英語:Non-uniform memory access,簡(jiǎn)稱NUMA)是一種為多處理器的電腦設(shè)計(jì)的內(nèi)存架構(gòu),內(nèi)存訪問時(shí)間取決于內(nèi)存相對(duì)于處理器的位置。在NUMA下,處理器訪問它自己的本地內(nèi)存的速度比非本地內(nèi)存(內(nèi)存位于另一個(gè)處理器,或者是處理器之間共享的內(nèi)存)快一些;
非統(tǒng)一內(nèi)存訪問架構(gòu)的特點(diǎn)是:被共享的內(nèi)存物理上是分布式的,所有這些內(nèi)存的集合就是全局地址空間。所以處理器訪問這些內(nèi)存的時(shí)間是不一樣的,顯然訪問本地內(nèi)存的速度要比訪問全局共享內(nèi)存或遠(yuǎn)程訪問外地內(nèi)存要快些。另外,NUMA中內(nèi)存可能是分層的:本地內(nèi)存,群內(nèi)共享內(nèi)存,全局共享內(nèi)存;
在NUMA中還有三個(gè)節(jié)點(diǎn)的概念:
?? ? ? ?本地節(jié)點(diǎn):對(duì)于某個(gè)節(jié)點(diǎn)中的所有CPU,此節(jié)點(diǎn)稱為本地節(jié)點(diǎn)。
? ? ? ? 鄰居節(jié)點(diǎn):與本地節(jié)點(diǎn)相鄰的節(jié)點(diǎn)稱為鄰居節(jié)點(diǎn)。
? ? ? ? 遠(yuǎn)端節(jié)點(diǎn):非本地節(jié)點(diǎn)或鄰居節(jié)點(diǎn)的節(jié)點(diǎn),稱為遠(yuǎn)端節(jié)點(diǎn)。
CPU訪問不同類型節(jié)點(diǎn)內(nèi)存的速度是不相同的,訪問本地節(jié)點(diǎn)的速度最快,訪問遠(yuǎn)端節(jié)點(diǎn)的速度最慢,即訪問速度與節(jié)點(diǎn)的距離有關(guān),距離越遠(yuǎn)訪問速度越慢,此距離稱作Node Distance。正是因?yàn)橛羞@個(gè)特點(diǎn),所以我們的應(yīng)用程序要盡量的減少不通CPU模塊之間的交互,也就是說,如果你的應(yīng)用程序能有方法固定在一個(gè)CPU模塊里,那么你的應(yīng)用的性能將會(huì)有很大的提升;
調(diào)度域(Scheduling Domain)
Scheduling Domains 是現(xiàn)代硬件技術(shù)尤其是多 CPU 多核技術(shù)發(fā)展的產(chǎn)物。現(xiàn)在,一個(gè)復(fù)雜的高端系統(tǒng)由上到下可以這樣構(gòu)成:
它是一個(gè) NUMA 架構(gòu)的系統(tǒng),系統(tǒng)中的每個(gè) Node 訪問系統(tǒng)中不同區(qū)域的內(nèi)存有不同的速度。
同時(shí)它又是一個(gè) SMP 系統(tǒng)。由多個(gè)物理 CPU(Physical Package) 構(gòu)成。這些物理 CPU 共享系統(tǒng)中所有的內(nèi)存。但都有自己獨(dú)立的 Cache 。
每個(gè)物理 CPU 又由多個(gè)核 (Core) 構(gòu)成,即 Multi-core 技術(shù)或者叫 Chip-level Multi processor(CMP) 。這些核都被集成在一塊 die 里面。一般有自己獨(dú)立的 L1 Cache,但可能共享 L2 Cache 。
每個(gè)核中又通過 SMT 之類的技術(shù)實(shí)現(xiàn)多個(gè)硬件線程,或者叫 Virtual CPU( 比如 Intel 的 Hyper-threading 技術(shù) ) 。這些硬件線程,邏輯上看是就是一個(gè) CPU 。它們之間幾乎所有的東西都共享。包括 L1 Cache,甚至是邏輯運(yùn)算單元 (ALU) 以及 Power 。
在上述系統(tǒng)中,最小的執(zhí)行單元是邏輯 CPU,進(jìn)程的調(diào)度執(zhí)行也是相對(duì)于邏輯 CPU 的。因此,后文皆簡(jiǎn)稱邏輯 CPU 為 CPU,是物理 CPU 時(shí)會(huì)特別說明。在這樣復(fù)雜的系統(tǒng),調(diào)度器要解決的一個(gè)首要問題就是如何發(fā)揮這么多 CPU 的性能,使得負(fù)載均衡。不存某些 CPU 一直很忙,進(jìn)程在排隊(duì)等待運(yùn)行,而某些 CPU 卻是處于空閑狀態(tài)。但是在這些 CPU 之間進(jìn)行 Load Balance 是有代價(jià)的,比如對(duì)處于兩個(gè)不同物理 CPU 的進(jìn)程之間進(jìn)行負(fù)載平衡的話,將會(huì)使得 Cache 失效。造成效率的下降。而且過多的 Load Balance 會(huì)大量占用 CPU 資源,為了解決上述的這些問題,內(nèi)核開發(fā)人員 Nick Piggin 等人在 Linux 2.6 中引入基于 Scheduling Domains 的解決方案。
? ? ? ? ? ??
每個(gè) Scheduling Domain 其實(shí)就是具有相同屬性的一組 cpu 的集合。并且跟據(jù) Hyper-threading, Multi-core, SMP, NUMA architectures 這樣的系統(tǒng)結(jié)構(gòu)劃分成不同的級(jí)別。不同級(jí)之間通過指針鏈接在一起,從而形成一種的樹狀的關(guān)系;
負(fù)載平衡就是針對(duì) Scheduling domain 的。從葉節(jié)點(diǎn)往上遍歷。直到所有的 domain 中的負(fù)載都是平衡的。當(dāng)然對(duì)不同的 domain 會(huì)有不同的策略識(shí)別是否負(fù)載不平衡,以及不同的調(diào)度策略。通過這樣的方式,從而很好的發(fā)揮眾多 cpu 的效率;
基于 Scheduling Domains 的調(diào)度器引入了一組新的數(shù)據(jù)結(jié)構(gòu)。下面先講一下兩個(gè)主要的數(shù)據(jù)結(jié)構(gòu):
struct sched_domain: 代表一個(gè) Scheduling Domain,也就是一個(gè) CPU 集合,這個(gè)集合里所有的 CPU 都具有相同的屬性和調(diào)度策略。Load Balance 是針對(duì)每個(gè) domain 里的 CPU 進(jìn)行的。這里要注意 Scheduling Domains 是分級(jí)的。像上節(jié)所講的復(fù)雜系統(tǒng)就分為 Allnuma_domain,Numa_domain, Phy_domain, Core_domain, Smt_domain(Cpu_domain) 五個(gè)等級(jí)。
struct sched_group: 每個(gè) Scheduling domain 都有一個(gè)或多個(gè) CPU group,每個(gè) group 都被 domain 當(dāng)做一個(gè)單獨(dú)的單元來對(duì)待。Load Balance 就是在這些 CPU group 之間的 CPU 進(jìn)行的。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??調(diào)度優(yōu)化
? ??
當(dāng)前主流服務(wù)器都是多核,多處理器,多NUMA等多CPU架構(gòu)系統(tǒng),很多程序都同時(shí)跑著服務(wù)器里面,怎么最大化利用當(dāng)前CPU資源,?讓整體運(yùn)行效率更高呢?
調(diào)度優(yōu)化的本質(zhì)?
?CPU資源和任務(wù)之間最優(yōu)匹配
這里討論CPU調(diào)度優(yōu)化一些比較常見的優(yōu)化點(diǎn),即包括怎么提升CPU性能,怎么提升單個(gè)程序性能,也包括怎么提升整個(gè)系統(tǒng)的性能,后面計(jì)劃會(huì)詳細(xì)討論關(guān)于性能優(yōu)化等內(nèi)容,本篇探討了一些優(yōu)化點(diǎn):
性能瓶頸
在進(jìn)行任何性能優(yōu)化前,有個(gè)很重要的前提原則是要找到性能瓶頸點(diǎn),然后才能針對(duì)性優(yōu)化,這要求我們學(xué)會(huì)用性能分析工具:
perf?
perf stat 采集程序運(yùn)行事件,用于分析指定程序的性能概況:
task-clock:目標(biāo)任務(wù)真真占用處理器的時(shí)間,單位是毫秒,我們稱之為任務(wù)執(zhí)行時(shí)間,后面是任務(wù)的處理器占用率(執(zhí)行時(shí)間和持續(xù)時(shí)間的比值)。持續(xù)時(shí)間值從任務(wù)提交到任務(wù)結(jié)束的總時(shí)間(總時(shí)間在stat結(jié)束之后會(huì)打印出來)。CPU 利用率,該值高,說明程序的多數(shù)時(shí)間花費(fèi)在 CPU 計(jì)算上而非 IO。
context-switches:上下文切換次數(shù),前半部分是切換次數(shù),后面是平均每秒發(fā)生次數(shù)(M是10的6次方)。
cpu-migrations:處理器遷移,linux為了位置各個(gè)處理器的負(fù)載均衡,會(huì)在特定的條件下將某個(gè)任務(wù)從一個(gè)處理器遷往另外一個(gè)處理器,此時(shí)便是發(fā)生了一次處理器遷移。即被調(diào)度器從一個(gè) CPU 轉(zhuǎn)移到另外一個(gè) CPU 上運(yùn)行。
page-fault:缺頁異常,linux內(nèi)存管理子系統(tǒng)采用了分頁機(jī)制,
當(dāng)應(yīng)用程序請(qǐng)求的頁面尚未建立、請(qǐng)求的頁面不在內(nèi)存中或者請(qǐng)求的頁面雖在在內(nèi)存中,
但是尚未建立物理地址和虛擬地址的映射關(guān)系是,會(huì)觸發(fā)一次缺頁異常。
cycles:任務(wù)消耗的處理器周期數(shù);處理器時(shí)鐘,一條機(jī)器指令可能需要多個(gè) cycles;
instructions:任務(wù)執(zhí)行期間產(chǎn)生的處理器指令數(shù),IPC(instructions perf cycle)
IPC(Instructions/Cycles )是評(píng)價(jià)處理器與應(yīng)用程序性能的重要指標(biāo)。(很多指令需要多個(gè)處理周期才能執(zhí)行完畢),
IPC越大越好,說明程序充分利用了處理器的特征。
branches:程序在執(zhí)行期間遇到的分支指令數(shù)。
branch-misses:預(yù)測(cè)錯(cuò)誤的分支指令數(shù)
cache-misses:cache時(shí)效的次數(shù)
cache-references:cache的命中次數(shù)
perf top?對(duì)系統(tǒng)性能進(jìn)行實(shí)時(shí)分析:
可以觀察到當(dāng)前函數(shù)CPU使用占比;
可以查看當(dāng)前系統(tǒng)最耗時(shí)的內(nèi)核函數(shù)或某個(gè)用戶進(jìn)程;
可以查看到當(dāng)前耗時(shí)的指令;
CPU 火焰圖
支持多種工具源,可以從包含堆棧跟蹤的任何配置文件數(shù)據(jù)生成火焰圖,包括從以下配置文件工具生成:
Linux: perf, eBPF, SystemTap, and ktap
Solaris, illumos, FreeBSD: DTrace
Mac OS X: DTrace and Instruments
Windows: Xperf.exe
可以查看哪些代碼路徑很熱(CPU占有率高)。
可以顯示堆棧路徑上CPU消耗,找到耗時(shí)的最多的函數(shù);
gperf 性能檢測(cè)
Gperftools是可以對(duì)用戶程序進(jìn)行性能統(tǒng)計(jì)分析。主要優(yōu)點(diǎn)之一是非常好的圖形輸出,低開銷和使用非常簡(jiǎn)單(檢查的應(yīng)用程序不需要任何重新編譯,只需預(yù)加載探查器的庫即可啟用分析,并且在需要時(shí)可以進(jìn)行可選的庫鏈接編譯);
可以顯示各個(gè)調(diào)用連上函數(shù)執(zhí)行占比,找到耗時(shí)異常的函數(shù),找到性能瓶頸點(diǎn);
性能優(yōu)化
局部性原理
局部性有兩種,即時(shí)間局部性和空間局部性。時(shí)間局部性是指當(dāng)一個(gè)數(shù)據(jù)被訪問后,它很有可能會(huì)在不久的將來被再次訪問,比如循環(huán)代碼中的數(shù)據(jù)或指令本身。而空間局部性指的是,當(dāng)程序訪問地址為x的數(shù)據(jù)時(shí),很有可能會(huì)緊接著訪問x周圍的數(shù)據(jù),比如遍歷數(shù)組或指令的順序執(zhí)行。由于這兩種局部性存在于大多數(shù)的程序中,硬件系統(tǒng)可以很好地預(yù)測(cè)哪些數(shù)據(jù)可以放入緩存,從而運(yùn)行得很好。
緩存優(yōu)化-緩存親和性
緩存訪問在設(shè)計(jì)多處理器調(diào)度時(shí)遇到的最后一個(gè)問題,是所謂的緩存親和度(cache affinity)。這個(gè)概念很簡(jiǎn)單:一個(gè)進(jìn)程在某個(gè)CPU上運(yùn)行時(shí),會(huì)在該CPU的緩存中維護(hù)許多狀態(tài)。下次該進(jìn)程在相同CPU上運(yùn)行時(shí),由于緩存中的數(shù)據(jù)而執(zhí)行得更快。相反,在不同的CPU上執(zhí)行,會(huì)由于需要重新加載數(shù)據(jù)而很慢(好在硬件保證的緩存一致性可以保證正確執(zhí)行)。因此多處理器調(diào)度應(yīng)該考慮到這種緩存親和性,并盡可能將進(jìn)程保持在同一個(gè)CPU上。
NUMA優(yōu)化
比起訪問remote memory,local memory 訪問不僅延遲低(100ns),而且也減少了對(duì)公共總線(interconnect)的競(jìng)爭(zhēng)。因此合理地放置數(shù)據(jù)(比如直接調(diào)用NUMA api)?, ?軟件調(diào)優(yōu)化基本上還是圍繞在盡量訪問本地內(nèi)存這一思路上。如果本地內(nèi)存已用完,那么盡量訪問本CPU下相臨節(jié)點(diǎn)的內(nèi)存,避免訪問跨CPU訪問最遠(yuǎn)端的內(nèi)存,可以提高20-30%性能,具體數(shù)據(jù)和當(dāng)前應(yīng)用相關(guān)。
CPU資源優(yōu)化
CPU獨(dú)占:獨(dú)占CPU資源,減少調(diào)度影響,提高系統(tǒng)性能;
CPU綁定:減少CPU上下文切換,提高系統(tǒng)性能;
中斷親和 :?中斷負(fù)載均衡,減輕其他CPU負(fù)擔(dān),提高系統(tǒng)性能;
進(jìn)程親和:減少CPU上下文切換,提高系統(tǒng)性能;
中斷隔離:減少中斷對(duì)CPU調(diào)度影響,提高系統(tǒng)性能;
內(nèi)存優(yōu)化
采用更大容量的內(nèi)存,減少內(nèi)存不足對(duì)性能影響,實(shí)現(xiàn)用空間換時(shí)間的性能優(yōu)化;
使用新內(nèi)存技術(shù),比如DDR4,好的內(nèi)存硬件可以減少內(nèi)存延遲,提高內(nèi)存訪問速度,從而提高系統(tǒng)性能。
時(shí)鐘優(yōu)化
時(shí)鐘芯片:采用更高精度時(shí)鐘芯片可以獲得更精確的時(shí)間,可以讓系統(tǒng)控制粒度更細(xì);
時(shí)鐘頻率:時(shí)鐘頻率調(diào)整,調(diào)高->可以達(dá)到更細(xì)的計(jì)時(shí)精度,提高任務(wù)調(diào)度的效率;調(diào)低->可以降低時(shí)鐘中斷的打擾和降低功耗;
優(yōu)先級(jí)優(yōu)化
優(yōu)先級(jí)調(diào)整(nice):調(diào)整進(jìn)程優(yōu)先級(jí),可以讓進(jìn)程運(yùn)行更快;
調(diào)度算法優(yōu)化
?linux 系統(tǒng)一些主線調(diào)度算法演進(jìn):
?O(n)調(diào)度算法?-2.4時(shí)代
O(n)調(diào)度器
調(diào)度器采用基于優(yōu)先級(jí)的設(shè)計(jì);
pick next算法非常簡(jiǎn)單:對(duì)runqueue中所有進(jìn)程的優(yōu)先級(jí)進(jìn)行依次進(jìn)行比較,選擇最高優(yōu)先級(jí)的進(jìn)程作為下一個(gè)被調(diào)度的進(jìn)程;
每次進(jìn)程切換時(shí), 內(nèi)核掃描可運(yùn)行進(jìn)程的鏈表, 計(jì)算優(yōu)先級(jí),然后選擇”最佳”進(jìn)程來運(yùn)行;
O(n)調(diào)度器面臨的問題
時(shí)間復(fù)雜度問題,時(shí)間復(fù)雜度是O(n),當(dāng)系統(tǒng)中的進(jìn)程很少的時(shí)候性能還可以,但是當(dāng)系統(tǒng)中的進(jìn)程逐漸增多,選擇下一個(gè)進(jìn)程的時(shí)間則是逐漸增大。而且當(dāng)系統(tǒng)中無可運(yùn)行的進(jìn)程時(shí),重新初始化進(jìn)程的時(shí)間片也是相當(dāng)耗時(shí),在系統(tǒng)中進(jìn)程很多的情況系下。
SMP擴(kuò)展問題。當(dāng)需要picknext下一個(gè)進(jìn)程時(shí),需要對(duì)整個(gè)runqueue隊(duì)列進(jìn)行加鎖的操作,spin_lock_irq(&runqueue_lock);當(dāng)系統(tǒng)中進(jìn)程數(shù)目比較多的時(shí)候,則在臨界區(qū)的時(shí)間就比較長(zhǎng),導(dǎo)致其余的CPU自旋比較浪費(fèi)
實(shí)時(shí)進(jìn)程的運(yùn)行效率問題,因?yàn)閷?shí)時(shí)進(jìn)程和普通進(jìn)程在一個(gè)列表中,每次查實(shí)時(shí)進(jìn)程時(shí),都需要全部掃描整個(gè)列表,導(dǎo)致實(shí)時(shí)進(jìn)程不是很“實(shí)時(shí)”
CPU資源浪費(fèi)問題:因?yàn)橄到y(tǒng)中只有一個(gè)runqueue,則當(dāng)運(yùn)行隊(duì)列中的進(jìn)程少于CPU的個(gè)數(shù)時(shí),其余的CPU則幾乎是idle狀態(tài),浪費(fèi)資源
cache緩存問題:當(dāng)系統(tǒng)中的進(jìn)程逐漸減少時(shí),原先在CPU1上運(yùn)行的進(jìn)程,不得不在CPU2上運(yùn)行,導(dǎo)致在CPU2上運(yùn)行時(shí),cacheline則幾乎是空白的,影響效率。
總之O(n)調(diào)度器有很多問題,不過有問題肯定要解決的。所以在Linux2.6引入了O(1)的調(diào)度器。
?O(1)調(diào)度算法 -2.6時(shí)代
? ? ? ? ? ????????????
O(1)調(diào)度器:
pick next算法借助于active數(shù)組,調(diào)度器只需按優(yōu)先級(jí)將下一個(gè)任務(wù)從特定活動(dòng)的運(yùn)行隊(duì)列中取出即可,無需遍歷runqueue,schedule()函數(shù)的時(shí)間復(fù)雜度為O(1)(把O(n)復(fù)雜度操作分?jǐn)偟匠R?guī)每一次操作中),改進(jìn)了前任調(diào)度器的可擴(kuò)展性問題;
消了前任算法定期更新所有進(jìn)程counter的操作,動(dòng)態(tài)優(yōu)先級(jí)的修改分布在進(jìn)程切換,時(shí)鐘tick中斷以及其它一些內(nèi)核函數(shù)中進(jìn)行;
O(1)調(diào)度器還更好地區(qū)分了交互式進(jìn)程和批處理式進(jìn)程,提供了大量啟示用于確定任務(wù)是受 I/O 限制還是受處理器限制算法,使調(diào)度更精細(xì);
O(1)調(diào)度器面臨的問題
O(1)調(diào)度器對(duì)NUMA支持不完善;
算法的主要復(fù)雜性來自動(dòng)態(tài)優(yōu)先級(jí)的計(jì)算,調(diào)度器根據(jù)平均睡眠時(shí)間和一些很難理解的經(jīng)驗(yàn)公式來修正進(jìn)程的優(yōu)先級(jí)以及區(qū)分交互式進(jìn)程,導(dǎo)致調(diào)度系統(tǒng)代碼的日趨復(fù)雜,難以維護(hù);
????CFS調(diào)度算法?-如今主流
CFS 背后的主要想法是維護(hù)為任務(wù)提供處理器時(shí)間方面的平衡(公平性)。這意味著應(yīng)給進(jìn)程分配相當(dāng)數(shù)量的處理器。分給某個(gè)任務(wù)的時(shí)間失去平衡時(shí)(意味著一個(gè)或多個(gè)任務(wù)相對(duì)于其他任務(wù)而言未被給予相當(dāng)數(shù)量的時(shí)間),應(yīng)給失去平衡的任務(wù)分配時(shí)間,讓其執(zhí)行;
CFS 在叫做vruntime-虛擬運(yùn)行時(shí)?的地方維持提供給某個(gè)任務(wù)的時(shí)間量。任務(wù)的虛擬運(yùn)行時(shí)越小, 意味著任務(wù)被允許訪問服務(wù)器的時(shí)間越短 — 其對(duì)處理器的需求越高;
CFS 不直接使用優(yōu)先級(jí)而是將其用作允許任務(wù)執(zhí)行的時(shí)間的衰減系數(shù)。低優(yōu)先級(jí)任務(wù)具有更高的衰減系數(shù),而高優(yōu)先級(jí)任務(wù)具有較低的衰減系數(shù)。這意味著與高優(yōu)先級(jí)任務(wù)相比,低優(yōu)先級(jí)任務(wù)允許任務(wù)執(zhí)行的時(shí)間消耗得更快。這是一個(gè)絕妙的解決方案,可以避免維護(hù)按優(yōu)先級(jí)調(diào)度的運(yùn)行隊(duì)列;
CFS 維護(hù)了一個(gè)以時(shí)間為順序的紅黑樹,任務(wù)存儲(chǔ)在以時(shí)間為順序的紅黑樹中,對(duì)處理器需求最多的任務(wù) (最低虛擬運(yùn)行時(shí))存儲(chǔ)在樹的左側(cè),處理器需求最少的任務(wù)(最高虛擬運(yùn)行時(shí))存儲(chǔ)在樹的右側(cè),pick_next算法選擇vruntime最小進(jìn)程運(yùn)行,即選取紅黑樹最左端的節(jié)點(diǎn)調(diào)度為下一個(gè)以便保持公平性;
?
?BFS & MuqSS-面向桌面或移動(dòng)設(shè)備調(diào)度器
BFS的原理十分簡(jiǎn)單,其實(shí)質(zhì)正是使用了O(1)調(diào)度器中的位圖的概念,所有進(jìn)程被安排到103個(gè)queue中,各個(gè)進(jìn)程不是按照優(yōu)先級(jí)而是按照優(yōu)先級(jí)區(qū)間被排列到各自所在的區(qū)間,每一個(gè)區(qū)間擁有一個(gè)queue:
BFS 是一個(gè)適用于桌面或移動(dòng)設(shè)備的調(diào)度器,設(shè)計(jì)地比較簡(jiǎn)潔,用于改善桌面應(yīng)用的交互性,減小響應(yīng)時(shí)間,提升用戶體驗(yàn)。它采用了全局單任務(wù)隊(duì)列設(shè)計(jì),不再讓每個(gè) CPU 都有獨(dú)立的運(yùn)行隊(duì)列。雖然使用單個(gè)全局隊(duì)列,需要引入隊(duì)列鎖來保證并發(fā)安全性,但是對(duì)于桌面系統(tǒng)而言,處理器通常都比較少,鎖的開銷基本可以忽略。BFS 每次會(huì)在任務(wù)鏈表中選擇具有最小 virtual deadline 的任務(wù)運(yùn)行。
MuqSS 是作者后來基于 BFS 改進(jìn)的一款調(diào)度器,同樣是用于桌面環(huán)境任務(wù)調(diào)度。它主要解決了 BFS 的兩個(gè)問題:
每次需要在對(duì)應(yīng)優(yōu)先級(jí)鏈表中遍歷查找需要執(zhí)行任務(wù),這個(gè)時(shí)間復(fù)雜度為 O(n)。所以新的調(diào)度器引入了跳表來解決該問題,從而將時(shí)間復(fù)雜度降低到 O(1)。
全局鎖爭(zhēng)奪的開銷優(yōu)化,采用 try_lock 替代 lock。
并行優(yōu)化
并行:多個(gè)任務(wù)在同一時(shí)刻一起發(fā)生;
并發(fā):多個(gè)任務(wù)在同一時(shí)刻只能有一個(gè)發(fā)生,CPU快速切換-操作系統(tǒng)分時(shí)復(fù)用,給人的感覺還是同時(shí)在跑,本質(zhì)還是串行執(zhí)行;并發(fā)的關(guān)鍵是你有處理多個(gè)任務(wù)的能力,不一定要同時(shí);并行的關(guān)鍵是你有同時(shí)處理多個(gè)任務(wù)的能力,必須在多核系統(tǒng)上。
在多核系統(tǒng)中需要并行編程提高CPU運(yùn)行效率
一般采用多線程來實(shí)現(xiàn)并行計(jì)算來縮短計(jì)算時(shí)間,提高多核系統(tǒng)整體性能;
通常是一個(gè)線程綁定一個(gè)核,可以實(shí)現(xiàn)多線程程序CPU利用率最大化;
盡量使用線程 local 數(shù)據(jù),減少共享數(shù)據(jù)訪問;
盡量使用線程棧內(nèi)存(local變量),減少指針引用,數(shù)據(jù)結(jié)構(gòu)內(nèi)存對(duì)齊(利用編譯指令),減少cache miss;
了解參考一些經(jīng)典成熟并行編程模型對(duì)你設(shè)計(jì)多線程并行程序大有裨益:
? ? ? ?https://zh.wikipedia.org/wiki/%E5%B9%B6%E8%A1%8C%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B
了解一些典型并行編程思想,OpenCL的GPU并行設(shè)計(jì),FPGA里面的多pipeline并行設(shè)計(jì),MapReduce大數(shù)據(jù)計(jì)數(shù)里面的分而治之;
如果不得不訪問共享數(shù)據(jù),盡量讓共享訪問代價(jià)最小化,讓鎖范圍最小,比如采用原子操作,無鎖編程等技術(shù);
? ? ? ?
鎖和無鎖設(shè)計(jì)優(yōu)化
如何正確有效的保護(hù)共享數(shù)據(jù)是編寫并行程序必須面臨的一個(gè)難題,通常的手段就是同步。同步可分為阻塞型同步(Blocking Synchronization)和非阻塞型同步( Non-blocking Synchronization),多線程里面難免需要訪問"共享內(nèi)存",如果不加鎖很容易導(dǎo)致結(jié)果異常,程序首先要保證正確,即使影響性能低也需要加鎖來防止錯(cuò)誤,此時(shí)該怎么提高CPU執(zhí)行性能呢??一個(gè)比較重要的優(yōu)化工作是鎖需要精心設(shè)計(jì)。
阻塞鎖
阻塞鎖通過改變了線程的運(yùn)行狀態(tài)。讓線程進(jìn)入阻塞狀態(tài)進(jìn)行等待,當(dāng)獲得相應(yīng)的信號(hào)(喚醒,時(shí)間) 時(shí),才可以進(jìn)入線程的準(zhǔn)備就緒狀態(tài),準(zhǔn)備就緒狀態(tài)的線程,通過競(jìng)爭(zhēng),進(jìn)入運(yùn)行狀態(tài);
mutex 主要用于線程間互斥訪問資源場(chǎng)景;
semaphore 主要用于多個(gè)線程同步場(chǎng)景;
讀寫鎖針主要用于讀多寫少場(chǎng)景;
非阻塞鎖
非阻塞鎖不會(huì)改變線程狀態(tài),使用時(shí)不會(huì)產(chǎn)生調(diào)度,通過CPU忙等待或者基于CAS(Compare - And - Swap)原子操作指令實(shí)現(xiàn)非阻塞訪問資源;
自旋鎖底層通過控制原子變量的值,讓其他CPU忙等待,cache親和性高和控制好鎖粒度,可以提高多線程訪問資源效率,主要用于加鎖時(shí)間極短且無阻塞點(diǎn)場(chǎng)景;
RCU鎖(Read-Copy Update)--非常重要一種無鎖設(shè)計(jì),對(duì)于被RCU保護(hù)的共享數(shù)據(jù)結(jié)構(gòu),讀者不需要獲得任何鎖就可以訪問它(因此不會(huì)導(dǎo)致鎖競(jìng)爭(zhēng),不會(huì)導(dǎo)致鎖競(jìng)爭(zhēng),內(nèi)存延遲以及流水線停滯,讀效率極高),但寫者在訪問它時(shí)首先拷貝一個(gè)副本,然后對(duì)副本進(jìn)行修改,最后使用一個(gè)回調(diào)(callback)機(jī)制在適當(dāng)?shù)臅r(shí)機(jī)把指向原來數(shù)據(jù)的指針重新指向新的被修改的數(shù)據(jù)。這個(gè)時(shí)機(jī)就是所有引用該數(shù)據(jù)的CPU都退出對(duì)共享數(shù)據(jù)的操作,RCU實(shí)際上是一種改進(jìn)的讀寫鎖,更能提高讀多寫少場(chǎng)景的系統(tǒng)性能;
原子操作可以保證指令以原子的方式執(zhí)行(鎖總線或者鎖CPU緩存)——執(zhí)行過程不被打斷,主要用于全局統(tǒng)計(jì)、引用計(jì)數(shù),無鎖設(shè)計(jì)等場(chǎng)景;
CAS操作(Compare And Set或是 Compare And Swap),現(xiàn)在幾乎所有的CPU指令都支持CAS的原子操作,X86下對(duì)應(yīng)的是 CMPXCHG 匯編指令。有了這個(gè)原子操作,我們就可以用其來實(shí)現(xiàn)各種無鎖(lock free)的數(shù)據(jù)結(jié)構(gòu),主要用于各種追求極限高性能場(chǎng)景,比如內(nèi)存數(shù)據(jù)庫,內(nèi)存消息隊(duì)列,DPDK的內(nèi)存池mempool,java 的Disruptor等;
真正無鎖-沒有資源沖突,每個(gè)線程只使用local數(shù)據(jù),最高級(jí)別的無鎖設(shè)計(jì),適合分而治之算法場(chǎng)景;
IO優(yōu)化
零拷貝:? 減少驅(qū)動(dòng)到協(xié)議棧之間內(nèi)存拷貝,減少用戶空間到內(nèi)核空間內(nèi)存拷貝,提升IO性能;
網(wǎng)卡硬件升級(jí):10G->25G->40G->100G->200G->400G->...;
kernelbypass:繞過內(nèi)核協(xié)議棧(路徑長(zhǎng),多核性能差),提高IO吞吐量;
? ?DPDK:?
Intel DPDK全稱Intel Data Plane Development Kit,是intel提供的數(shù)據(jù)平面開發(fā)工具集,為Intel architecture(IA)處理器架構(gòu)下用戶空間高效的數(shù)據(jù)包處理提供庫函數(shù)和驅(qū)動(dòng)的支持,它不同于Linux系統(tǒng)以通用性設(shè)計(jì)為目的,而是專注于網(wǎng)絡(luò)應(yīng)用中數(shù)據(jù)包的高性能處理,適合高性能網(wǎng)關(guān)(IO需求大)場(chǎng)景;
PMD用戶態(tài)驅(qū)動(dòng),使用無中斷方式直接操作網(wǎng)卡的接收和發(fā)送隊(duì)列;
采用HugePage減少TLB Miss;
DPDK采用向量SIMD指令優(yōu)化性能;
CPU親緣性和獨(dú)占;
內(nèi)存對(duì)齊:根據(jù)不同存儲(chǔ)硬件的配置來優(yōu)化程序,確保對(duì)象位于不同channel和rank的起始地址,這樣能保證對(duì)象并并行加載,性能也能夠得到極大的提升;
Cache對(duì)齊,提高cache訪問效率:
NUMA親和,提高numa內(nèi)存訪問性能;
減少進(jìn)程上下文切換:保證活躍進(jìn)程數(shù)目不超過CPU個(gè)數(shù);減少堵塞函數(shù)的調(diào)用,盡量采樣無鎖數(shù)據(jù)結(jié)構(gòu);
利用空間局部性,采用預(yù)取Prefetch,在數(shù)據(jù)被用到之前就將其調(diào)入緩存,增加緩存命中率;
充分挖掘網(wǎng)卡的潛能:借助現(xiàn)代網(wǎng)卡支持的分流(RSS, FDIR)和卸載(TSO,chksum)等特性;
? ?XDP:
?XDP(eXpress Data Path)為L(zhǎng)inux內(nèi)核提供了高性能、可編程的網(wǎng)絡(luò)數(shù)據(jù)路徑。由于網(wǎng)絡(luò)包在還未進(jìn)入網(wǎng)絡(luò)協(xié)議棧之前就處理,它給Linux網(wǎng)絡(luò)帶來了巨大的性能提升(性能比DPDK還要高)
在網(wǎng)絡(luò)協(xié)議棧前處理
無鎖設(shè)計(jì)
批量I/O操作
輪詢式
直接隊(duì)列訪問
DDIO(網(wǎng)卡直接IO),支持硬件offload加速
支持eBPF,高效開發(fā),安全可靠,性能好
和內(nèi)核耦合緊密,適合基于內(nèi)核網(wǎng)絡(luò)組件平滑演進(jìn)高性能方案,比如DDOS防護(hù),網(wǎng)絡(luò)采樣,高性能防火墻;
? P4?
p4 為一種高級(jí)可編程協(xié)議無關(guān)處理語言,結(jié)合可編程交換機(jī)芯片,編程能力強(qiáng),可以實(shí)現(xiàn)業(yè)務(wù)offload 到硬件,轉(zhuǎn)發(fā)面 p4lang 定制開發(fā),控制面可通過 Apache Thrift、gRPC 接口遠(yuǎn)程管理,生態(tài)繁榮包括P4 Runtime、Stratum;
性能高,1.8T ~ 6.5T 線速轉(zhuǎn)發(fā),更低時(shí)延;
每Tbps設(shè)備成本大幅降低;
主要應(yīng)用場(chǎng)景是大流量的邊界網(wǎng)關(guān),大流量無狀態(tài)網(wǎng)關(guān),大流量狀態(tài)網(wǎng)關(guān)(當(dāng)前P4交換機(jī)對(duì)內(nèi)存容量支持有限,對(duì)配置量有一定的限制);
時(shí)空互換
Per CPU
Per-CPU是基于空間換時(shí)間的方法, 讓每個(gè)CPU都有自己的私有數(shù)據(jù)段(放在L1中),并將一些變量私有化到?每個(gè)CPU的私有數(shù)據(jù)段中. 單個(gè)CPU在訪問自己的私有數(shù)據(jù)段時(shí), 不需要考慮其他CPU之間的競(jìng)爭(zhēng)問題,也不存在同步的問題. ?注意只有在該變量在各個(gè)CPU上邏輯獨(dú)立時(shí)才可使用。
指令并行
通過展開循環(huán)降低循環(huán)開銷,提高指令并行執(zhí)行效率;
向量指令
采用SIMD擴(kuò)展指令集來優(yōu)化指令執(zhí)行效率;
分支預(yù)測(cè)
分支預(yù)測(cè)采用空間換時(shí)間方式,直接預(yù)測(cè)分支條件,把分支指令填入流水線,如果預(yù)測(cè)失敗,再回滾清空流水線,重新選擇分支,通過采用有效的預(yù)測(cè)算法,可以極大提高CPU流水線的執(zhí)行效率,我們需要合理利用這個(gè)特性,減少分支判斷,在代碼中采用編譯指令優(yōu)化提供分支預(yù)測(cè)準(zhǔn)確性,比如在linux內(nèi)核中,提分支預(yù)測(cè)的信息提供給編譯器:?likely(x)? 表示x的值為真的可能性更大;unlikely(x)? ?表示x的值為假的可能性更大;這樣編譯器對(duì)代碼進(jìn)行優(yōu)化,以減少指令跳轉(zhuǎn)帶來的性能下降。
緩存系統(tǒng):各種cache優(yōu)化,用空間換時(shí)間;
BIOS優(yōu)化
BIOS(基本輸入/輸出系統(tǒng))是主板上的一個(gè)小內(nèi)存,其數(shù)據(jù)定義了系統(tǒng)的配置。某些數(shù)據(jù)被寫入死存儲(chǔ)器(ROM),因此無法更改。另一方面,某些配置可以從BIOS配置中訪問,我們?cè)趩?dòng)PC時(shí)通過按鍵激活該配置。
超線程優(yōu)化(Hyper-Threading)
超線程,是一種用于提升CPU計(jì)算并行度的處理器技術(shù),用一個(gè)物理核模擬兩個(gè)邏輯核。這兩個(gè)邏輯核擁有自己的中斷、狀態(tài),但是共用物理核的計(jì)算資源(寄存器)。超線程技術(shù)旨在提高CPU計(jì)算資源的使用率,從而提高計(jì)算并行度。但是超線程也有副作用,會(huì)產(chǎn)生訪問cache的競(jìng)爭(zhēng),會(huì)導(dǎo)致更多的cache不命中(cache-miss),增加線程間的通信負(fù)載。加大內(nèi)存的通信帶寬,I/O總線的壓力,所以對(duì)于一些高性能程序,一般是需要關(guān)閉超線程的;
電源模式
如果服務(wù)器想獲得最大的吞吐量或最低的延遲,修改電源模式為最大性能,可以提高服務(wù)器的性能;
Lockstep模式
鎖步模式對(duì)內(nèi)存進(jìn)行了更高的校驗(yàn),提升了系統(tǒng)的可靠性,但是降低了內(nèi)存訪問的帶寬和延時(shí),對(duì)于實(shí)時(shí)性要求高,吞吐量大的業(yè)務(wù)場(chǎng)景不適用,對(duì)于這些場(chǎng)景從系統(tǒng),軟件和方案層面都有完善的保護(hù)機(jī)制,所以建議關(guān)閉;
Turbo Mode
Turbo boost就是Intel的睿頻加速技術(shù),通常所說的自動(dòng)超頻技術(shù),主要用于提升處理器的頻率,最大程度發(fā)揮處理器性能;
批量合并
網(wǎng)絡(luò) IO 和磁盤 IO,合并操作和批量操作往往能提升吞吐量,提高性能。
redis,mysql,kafak等采用批量操作都可以極大提升性能;
預(yù)處理
預(yù)處理策略就是提前做好一些準(zhǔn)備工作,這樣可以提高后續(xù)處理性能;
比如網(wǎng)站頁面資源的提前加載,可以顯著地提升頁面下載性能;
比如CPU 預(yù)取指令,提前將所需要的數(shù)據(jù)和指令取出來,可以提高流水線效率和緩存效率;
惰性求值
惰性處理策略就是盡量將操作(比如計(jì)算),推遲到必需執(zhí)行的時(shí)刻,這樣很可能避免多余的操作。
Linux COW(Copy On Write,寫時(shí)復(fù)制)機(jī)制,比如fork 調(diào)用只有真正用到資源時(shí)候才拷貝;
中斷后半部分優(yōu)化,把可延遲函數(shù)放到延后處理,從而提高中斷處理整體效率;
缺頁中斷處理,不需要進(jìn)程把所有內(nèi)存頁載入內(nèi)存,只有需要的時(shí)候再加載,這樣可以減少大量無效內(nèi)存操作,提高整體性能;
架構(gòu)優(yōu)化
系統(tǒng)資源優(yōu)化: 物理機(jī)器->集群->虛擬化->云計(jì)算->容器->k8s編排器;
應(yīng)用架構(gòu)優(yōu)化:?單體應(yīng)用->基于組件->面向服務(wù)->微服務(wù);
軟件工程優(yōu)化:?瀑布模型->敏捷開發(fā)->DevOps->智能化工程,主要是提高研發(fā)效能,建設(shè)產(chǎn)品的性能測(cè)試CI/CD自動(dòng)化流水線,每個(gè)優(yōu)化點(diǎn)都可以及時(shí)查看到性能指標(biāo)變化和對(duì)比,從小作坊到標(biāo)準(zhǔn)化,工業(yè)化,智能化發(fā)展;
算法優(yōu)化
算法復(fù)雜度優(yōu)化:O(1)? < O(lgn)? <? O(n)?<? O(nlgn)? < O(n^2)< O(n^3)<O(2^n)? < O(n!) < O(n^n);
數(shù)據(jù)結(jié)構(gòu)優(yōu)化:hash結(jié)構(gòu) > 樹型結(jié)構(gòu)?> 線性結(jié)構(gòu);
代碼優(yōu)化
循環(huán)優(yōu)化:適當(dāng)展開循環(huán),可以讓指令并行執(zhí)行,提供搞性能;
條件判斷:減少條件判斷語句,可以減少分支預(yù)測(cè)失敗概率,提升CPU流水線效率,從而提升性能;
表達(dá)式優(yōu)化:?優(yōu)化布爾邏輯可以減少不必要計(jì)算;使++i而不使用i++可以減少中間臨時(shí)變量;
采用位運(yùn)算:如果沒有越界風(fēng)險(xiǎn),使用位運(yùn)算符合計(jì)算機(jī)計(jì)算模型,效率更高;
內(nèi)存&cache對(duì)齊:數(shù)據(jù)結(jié)構(gòu)最好是cache 對(duì)齊的整數(shù)倍,把高頻使用的屬性,放到最前面,這樣可以提高cache命中效率,減少Cache miss;
指針優(yōu)化:盡量減少指針使用,指針跳轉(zhuǎn)會(huì)導(dǎo)致Cache miss;
向量化:合適使用SIMD高級(jí)指令可以優(yōu)化代碼;
插入其他語言:插入?yún)R編,優(yōu)化高頻函數(shù);采用CPython優(yōu)化python代碼;
遞歸優(yōu)化:盡量把遞歸修改為循環(huán),減少遞歸調(diào)用代價(jià);
編譯優(yōu)化
編譯器優(yōu)化:O0 -->> O1 -->> O2 -->> O3,來額外的性能提升;
編譯器API:使用內(nèi)聯(lián)函數(shù),使用內(nèi)存對(duì)齊API,使用cache對(duì)齊API等 ,可以更好讓編譯器優(yōu)化代碼,減少調(diào)用指令,提高性能;
JIt編譯器優(yōu)化:使用Jit技術(shù),可以把中間代碼生成本地指令,提升代碼執(zhí)行效率;
?????????????????優(yōu)化無止境,上面每一個(gè)優(yōu)化點(diǎn),都可以更詳細(xì)展開講,更多是需要我們深入理解計(jì)算機(jī)原理,才能找到得更多優(yōu)化點(diǎn),讓我們向頂級(jí)程序員邁進(jìn);
—END—
關(guān)于linux調(diào)度系統(tǒng)系列文章終于完結(jié),讓我們期待下個(gè)系列吧。
想要獲取linux調(diào)度全景指南精簡(jiǎn)版,關(guān)注公眾號(hào)回復(fù)“調(diào)度”即可獲取?;貜?fù)其他消息,獲取更多內(nèi)容;
? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ??
往期推薦
Linux調(diào)度系統(tǒng)全景指南(上篇)
Linux調(diào)度系統(tǒng)全景指南(中篇)
Linux調(diào)度系統(tǒng)全景指南(下篇)
C++模版的本質(zhì)
C++內(nèi)存管理全景指南
云網(wǎng)絡(luò)丟包故障定位全景指南
騰訊資深工程師,一起修煉深厚內(nèi)功
總結(jié)
以上是生活随笔為你收集整理的Linux调度系统全景指南(终结篇)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux调度系统全景指南(下篇)
- 下一篇: 万字整理,图解Linux内存管理所有知识