golang 重要知識:golang 調(diào)度

摘要

Go 的調(diào)度機(jī)制相當(dāng)于我們微服務(wù)里的基礎(chǔ)組件。很多運(yùn)行時(shí)操作都涉及到了調(diào)度的關(guān)聯(lián)。本文會(huì)細(xì)聊調(diào)度概念,策略,以及它的機(jī)制。當(dāng)然,也少不了最常提及的 GMP 模型。

一拳话、調(diào)度是什么?

計(jì)算機(jī)的資源有限的,像 CPU种吸,內(nèi)存都是固定的坚俗。但是同一時(shí)間可能會(huì)有多個(gè)任務(wù)要去完成速缆,比如操作系統(tǒng)的定時(shí)監(jiān)控送滞,用戶程序的運(yùn)行等褂微。

怎么讓資源最大化的完成任務(wù),這是調(diào)度需要考慮的關(guān)鍵點(diǎn)园爷。

調(diào)度可以理解為一個(gè)指揮員求厕,指導(dǎo)我們的程序按照一定的規(guī)則去獲取資源,然后去執(zhí)行里面的指令扰楼。

調(diào)度分配

那么呀癣,一般的規(guī)則有哪些呢?

常見的調(diào)度策略有 2 種弦赖,一種是協(xié)作式調(diào)度项栏,會(huì)讓程序順利的完成自己的任務(wù),再把資源騰出來給其他程序使用蹬竖。

另一種是搶占式調(diào)度沼沈,也就是讓程序按一定的時(shí)間去占有這些資源,時(shí)間到了就被迫讓出現(xiàn)有資源币厕,給其他的程序輪流使用列另。

協(xié)作式調(diào)度有利于程序?qū)W⒌耐瓿勺约旱娜蝿?wù),但也可能會(huì)造成其他程序一直餓死旦装,得不到執(zhí)行访递。

協(xié)作式調(diào)度

搶占式調(diào)度有利于程序在資源的利用上雨露均沾,但是在不斷的切換過程中同辣,將會(huì)使得程序原本 10 ms 能完成的事拷姿,不得不延遲多幾 ms。

搶占式調(diào)度

注:Linux 操作系統(tǒng)也是采用了搶占式調(diào)度旱函,并且使用了 CFS:完全公平調(diào)度算法响巢。通過對程序大致的運(yùn)行時(shí)間來平衡調(diào)度,讓越?jīng)]有執(zhí)行過的程序棒妨,越快被調(diào)度到踪古。

當(dāng)前大多數(shù)操作系統(tǒng)都是采用搶占式調(diào)度來執(zhí)行程序的含长,畢竟很多操作系統(tǒng)都是面向用戶,需要很高的響應(yīng)速度伏穆,而且只要切換程序的周期夠短拘泞,例如 50ms,那對于用戶來講枕扫,就像沒切換一樣陪腌。

二、golang 的調(diào)度

上面提及到搶占式調(diào)度會(huì)有個(gè)頻繁切換的過程烟瞧,在切換時(shí)诗鸭,需要不斷的保存或恢復(fù)上下文信息。

而這會(huì)涉及到操作系統(tǒng)內(nèi)核態(tài)和用戶態(tài)的切換参滴,性能損耗會(huì)很大强岸。

對此,golang 實(shí)現(xiàn)了屬于自己的調(diào)度模型砾赔,采用了基于協(xié)作的搶占式調(diào)度蝌箍。之所以是"協(xié)作"的,是因?yàn)?Go 的調(diào)度時(shí)機(jī)是由用戶自己設(shè)置的暴心,而這里的用戶指的是 golang 的運(yùn)行時(shí) runtime妓盲。

它會(huì)在下面的事件發(fā)生時(shí)進(jìn)行調(diào)度觸發(fā):

  • 使用關(guān)鍵字 go
  • 垃圾回收
  • 系統(tǒng)調(diào)用,如訪問硬盤
  • 同步阻塞調(diào)用酷勺,如 使用 mutex本橙、channel

如果上面什么事件都沒發(fā)生扳躬,則會(huì)有 sysmon 來監(jiān)控 goroutine 的運(yùn)行情況脆诉,對長時(shí)間運(yùn)行的 goroutine 進(jìn)行標(biāo)記。一旦 goroutine 被標(biāo)記了贷币,那么它就會(huì)下次發(fā)生函數(shù)調(diào)用時(shí)击胜,將自己掛起,再觸發(fā)調(diào)度检号。

這里需要說明下的是葵袭,runtime 它相當(dāng)于 Java 的虛擬機(jī)届氢,負(fù)責(zé)了 Go 的很多東西,例如調(diào)度辰斋,垃圾回收、內(nèi)存管理等瘸味,可以說是涵蓋了 Go 的基礎(chǔ)引擎了宫仗。

更重要的是 runtime 是運(yùn)行在用戶態(tài)上的,相當(dāng)于 Go 的調(diào)度是在用戶態(tài)這一層進(jìn)行的旁仿。

這樣藕夫,每當(dāng) Go 有調(diào)度產(chǎn)生時(shí),就不會(huì)伴隨著用戶態(tài)和內(nèi)核態(tài)的切換,而是像前面提到過的策略那樣去觸發(fā)調(diào)度毅贮,這就降低了并發(fā)時(shí)的內(nèi)核態(tài)與用戶態(tài)的切換成本了办悟。

三、golang 的 GPM 模型

為了實(shí)現(xiàn) golang 的調(diào)度滩褥,golang 抽象出了三個(gè)結(jié)構(gòu)病蛉,也就是我們常見的 G、P铸题、M铡恕。

G:也就是協(xié)程 goroutine,由 Go runtime 管理丢间。我們可以認(rèn)為它是用戶級別的線程探熔。

goroutine 非常的輕量,初始分配只有 2KB烘挫,當(dāng)椌骷瑁空間不夠用時(shí),會(huì)自動(dòng)擴(kuò)容饮六。同時(shí)其垄,自身存儲(chǔ)了執(zhí)行 stack 信息、goroutine 狀態(tài)以及 goroutine 的任務(wù)函數(shù)等卤橄。

P:processor 處理器绿满。P 的數(shù)量默認(rèn)跟 CPU 的核心數(shù)一樣,如果是多核的 CPU窟扑,則會(huì)有多個(gè) P 會(huì)被創(chuàng)建喇颁。

每當(dāng)有 goroutine 要?jiǎng)?chuàng)建時(shí),會(huì)被添加到 P 上的 goroutine 本地隊(duì)列上嚎货,如果 P 的本地隊(duì)列已滿橘霎,則會(huì)維護(hù)到全局隊(duì)列里。

在進(jìn)行調(diào)度時(shí)殖属,會(huì)優(yōu)先從本地隊(duì)列獲取 goroutine 來執(zhí)行姐叁。

如果本地隊(duì)列沒有,會(huì)從其他的 P 上偷取 goroutine洗显。

如果其他 P 上也沒有外潜,則會(huì)從全局隊(duì)列上獲取 goroutine。

這樣通過上面的策略挠唆,就能盡最大努力保證有 goroutine 可運(yùn)行处窥。

M:系統(tǒng)線程。在 M 上有調(diào)度函數(shù)损搬,它是真正的調(diào)度執(zhí)行者碧库,M 需要跟 P 綁定柜与,并且會(huì)讓 P 按上面的原則挑出個(gè) goroutine 來執(zhí)行。

M 雖然從 P 上挑選了 G 執(zhí)行嵌灰,但 M 并不保存 G 的上下文信息弄匕,而是 G 自己保存了相關(guān)信息,這樣有利于轉(zhuǎn)移到其他 M 上沽瞭,在不同的 M 上運(yùn)行迁匠。

GPM模型

GPM 模型的優(yōu)勢點(diǎn)在于 G 包含了執(zhí)行任務(wù)相關(guān)信息,M 提供了執(zhí)行環(huán)境驹溃,并且有調(diào)度機(jī)制城丧。而 P 則是他們兩者的粘合劑。

假如沒有 P 豌鹤。那么 M 就會(huì)有爭奪 G 的競爭問題亡哄,并且 M 的數(shù)量會(huì)不可控,會(huì)出現(xiàn)過多的 M 去處理 G布疙。

一旦超過了 CPU 的核心數(shù)蚊惯,那么就會(huì)將性能耗費(fèi)在上下文切換過程中。

有了 P 這一層后灵临,M 優(yōu)先從 P 的本地隊(duì)列獲取 goroutine截型,減少并發(fā)競爭。并且保證了最多跟 CPU 核心數(shù)一樣的 goroutine 數(shù)量在并行運(yùn)行儒溉,充分利用了多核優(yōu)勢宦焦,又不被濫用。

總結(jié)

相信看過本文后顿涣,各位對 Golang 的調(diào)度有了一定的了解波闹。正是因?yàn)榛趨f(xié)作的搶占式調(diào)度和 GMP 模型,Golang 的高并發(fā)高性能才有了底層保障园骆。當(dāng)然舔痪,大伙也可以深入到源碼去分析這些調(diào)度機(jī)制寓调,這樣離大神就更近一步了 ?...

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锌唾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子夺英,更是在濱河造成了極大的恐慌晌涕,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痛悯,死亡現(xiàn)場離奇詭異余黎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)载萌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門惧财,熙熙樓的掌柜王于貴愁眉苦臉地迎上來巡扇,“玉大人,你說我怎么就攤上這事垮衷√瑁” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵搀突,是天一觀的道長刀闷。 經(jīng)常有香客問我,道長仰迁,這世上最難降的妖魔是什么甸昏? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮徐许,結(jié)果婚禮上施蜜,老公的妹妹穿的比我還像新娘。我一直安慰自己雌隅,他們只是感情好花墩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澄步,像睡著了一般冰蘑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上村缸,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天祠肥,我揣著相機(jī)與錄音,去河邊找鬼梯皿。 笑死仇箱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的东羹。 我是一名探鬼主播剂桥,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼属提!你這毒婦竟也來了权逗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤冤议,失蹤者是張志新(化名)和其女友劉穎斟薇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恕酸,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡堪滨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蕊温。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袱箱。...
    茶點(diǎn)故事閱讀 39,739評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡遏乔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出发笔,到底是詐尸還是另有隱情按灶,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布筐咧,位于F島的核電站鸯旁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏量蕊。R本人自食惡果不足惜铺罢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望残炮。 院中可真熱鬧韭赘,春花似錦、人聲如沸势就。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽苞冯。三九已至袖牙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舅锄,已是汗流浹背鞭达。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留皇忿,地道東北人畴蹭。 一個(gè)月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像鳍烁,于是被迫代替她去往敵國和親叨襟。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容