2021-07-03

?golang?行情推送[1]的分享,有人針對(duì) ppt 的內(nèi)容問(wèn)了我兩個(gè)問(wèn)題,一個(gè)是在 docker 下 golang 的 gomaxprocs 初始化混亂問(wèn)題,另一個(gè)是 golang runtime.gomaxprocs 配置多少為合適?

golang runtime

Golang 的 runtime 調(diào)度是依賴 pmg 的角色抽象,p 為邏輯處理器愁溜,m 為執(zhí)行體(線程),g 為協(xié)程媒役。p 的 runq 隊(duì)列中放著可執(zhí)行的 goroutine 結(jié)構(gòu)祝谚。golang 默認(rèn) p 的數(shù)量為 cpu core 數(shù)目,比如物理核心為 8 cpu core酣衷,那么 go processor 的數(shù)量就為 8交惯。另外,同一時(shí)間一個(gè) p 只能綁定一個(gè) m 線程穿仪,pm 綁定后自然就找 g 和運(yùn)行 g席爽。

那么增加 processor 的數(shù)量,是否可以用來(lái)加大 runtime 對(duì)于協(xié)程的調(diào)度吞吐啊片?

大多 golang 的項(xiàng)目偏重網(wǎng)絡(luò) io只锻,network io 在 netpoll 設(shè)計(jì)下都是非阻塞的,所涉及到的 syscall 不會(huì)阻塞紫谷。如果是 cpu 密集的業(yè)務(wù)齐饮,增加多個(gè) processor 也沒(méi)用,畢竟 cpu 計(jì)算資源就這些笤昨,居然還想著來(lái)回的切換祖驱??? 所以,多數(shù)場(chǎng)景下單純?cè)黾?processor 是沒(méi)什么用的瞒窒。

當(dāng)然捺僻,話不絕對(duì),如果你的邏輯含有不少的 cgo 及阻塞 syscall 的操作,那么增加 processor 還是有效果的匕坯,最少在我實(shí)際項(xiàng)目中有效果束昵。原因是這類操作有可能因?yàn)檫^(guò)慢引起阻塞,在阻塞期間的 p 被 mg 綁定一起葛峻,其他 m 無(wú)法獲取 p 的所有權(quán)锹雏。雖然在 findrunnable steal 機(jī)制里,其他 p 的 m 可以偷該 p 的任務(wù)术奖,但在解綁 p 之前終究還是少了一條并行通道逼侦。另外,runtime 的 sysmon 周期性的檢查長(zhǎng)時(shí)間阻塞的 pmg腰耙, 并搶占并解綁 p。

golang 在 docker 下的問(wèn)題

在微服務(wù)體系下服務(wù)的部署通常是放在 docker 里的铲球。一個(gè)宿主機(jī)里跑著大量的不同服務(wù)的容器挺庞。為了避免資源沖突,通常會(huì)合理地對(duì)每個(gè)容器做 cpu 資源控制稼病。比如給一個(gè) golang 服務(wù)的容器限定了 2 cpu core 的資源选侨,容器內(nèi)的服務(wù)不管怎么折騰,也確實(shí)只能用到大約 2 個(gè) cpu core 的資源然走。

但 golang 初始化 processor 數(shù)量是依賴 /proc/cpuinfo 信息的援制,容器內(nèi)的 cpuinfo 是跟宿主機(jī)一致的,這樣導(dǎo)致容器只能用到 2 個(gè) cpu core芍瑞,但 golang 初始化了跟物理 cpu core 相同數(shù)量的 processor晨仑。

//?xiaorui.cc

限制2核左右

root@xiaorui.cc:~#?docker?run?-tid?--cpu-period?100000?--cpu-quota?200000?ubuntu

容器內(nèi)

root@a4f33fdd0240:/#?cat?/proc/cpuinfo|?grep?"processor"|?wc?-l

48

runtime processor 多了會(huì)出現(xiàn)什么問(wèn)題?

一個(gè)是 runtime findrunnable 時(shí)產(chǎn)生的損耗拆檬,另一個(gè)是線程引起的上下文切換洪己。

runtime 的 findrunnable 方法是解決 m 找可用的協(xié)程的函數(shù),當(dāng)從綁定 p 本地 runq 上找不到可執(zhí)行的 goroutine 后竟贯,嘗試從全局鏈表中拿答捕,再拿不到從 netpoll 和事件池里拿,最后會(huì)從別的 p 里偷任務(wù)屑那。全局 runq 是有鎖操作拱镐,其他偷任務(wù)使用了 atomic 原子操作來(lái)規(guī)避 futex 競(jìng)爭(zhēng)下陷入切換等待問(wèn)題,但 lock free 在競(jìng)爭(zhēng)下也會(huì)有忙輪詢的狀態(tài)持际,比如不斷的嘗試沃琅。

//?xiaorui.cc

//?全局?runq

ifsched.runqsize?!=0{

lock(&sched.lock)

gp?:=?globrunqget(_p_,0)

unlock(&sched.lock)

ifgp?!=nil{

returngp,false

}

}

...

//?嘗試4次從別的p偷任務(wù)

fori?:=0;?i?<4;?i++?{

forenum?:=?stealOrder.start(fastrand());?!enum.done();?enum.next()?{

ifsched.gcwaiting?!=0{

gototop

}

stealRunNextG?:=?i?>2//?first?look?for?ready?queues?with?more?than?1?g

ifgp?:=?runqsteal(_p_,?allp[enum.position()],?stealRunNextG);?gp?!=nil{

returngp,false

}

}

}

...

通過(guò) godebug 可以看到全局隊(duì)列及各個(gè) p 的 runq 里等待調(diào)度的任務(wù)量。有不少 p 是空的选酗,那么勢(shì)必會(huì)引起 steal 偷任務(wù)阵难。另外,runqueue 的大小遠(yuǎn)超其他 p 的總和芒填,說(shuō)明大部分任務(wù)在全局里呜叫,全局又是把大鎖空繁。

隨著調(diào)多 runtime processor 數(shù)量,相關(guān)的 m 線程自然也就跟著多了起來(lái)朱庆。linux 內(nèi)核為了保證可執(zhí)行的線程在調(diào)度上雨露均沾盛泡,按照內(nèi)核調(diào)度算法來(lái)切換就緒狀態(tài)的線程,切換又引起上下文切換娱颊。上下文切換也是性能的一大殺手傲诵。findrunnable 的某些鎖競(jìng)爭(zhēng)也會(huì)觸發(fā)上下文切換。

下面是我這邊一個(gè)行情推送服務(wù)壓測(cè)下的 vmstat 監(jiān)控?cái)?shù)據(jù)箱硕。首先把容器的的 cpu core 限制為 8拴竹,再先后測(cè)試 processor 為 8 和 48 的情況。圖的上面是 processor 為 8 的情況剧罩,下面為 processor 為 48 的情況栓拜。看圖可以直觀地發(fā)現(xiàn)當(dāng) processor 調(diào)大后惠昔,上下文切換(cs)明顯多起來(lái)幕与,另外等待調(diào)度的線程也多了。

另外從 qps 的指標(biāo)上也可以反映多 processor 帶來(lái)的性能損耗镇防。通過(guò)下圖可以看到當(dāng) runtime.GOMAXPROCS 為固定的 cpu core 數(shù)時(shí)啦鸣,性能最理想。后面隨著 processor 數(shù)量的增長(zhǎng)来氧,qps 指標(biāo)有所下降诫给。

通過(guò) golang tool trace 可以分析出協(xié)程調(diào)度等待時(shí)間越來(lái)越長(zhǎng)了。

解決 docker 下的 golang gomaxprocs 校對(duì)問(wèn)題

有兩個(gè)方法可以準(zhǔn)確校對(duì) golang 在 docker 的 cpu 獲取問(wèn)題啦扬。

要么在 k8s pod 里加入 cpu 限制的環(huán)境變量蝙搔,容器內(nèi)的 golang 服務(wù)在啟動(dòng)時(shí)獲取關(guān)于 cpu 的信息。

要么解析 cpu.cfs_period_us 和 cpu.cfs_quota_us 配置來(lái)計(jì)算 cpu 資源考传。社區(qū)里有不少這類的庫(kù)可以使用吃型,uber的automaxprocs[2]可以兼容 docker 的各種 cpu 配置。

總結(jié)

建議 gomaxprocs 配置為 cpu core 數(shù)量就可以了僚楞,Go 默認(rèn)就是這個(gè)配置勤晚,無(wú)需再介入。如果涉及到阻塞 syscall泉褐,可以適當(dāng)?shù)恼{(diào)整 gomaxprocs 大小赐写,但一定要用指標(biāo)數(shù)據(jù)說(shuō)話!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膜赃,一起剝皮案震驚了整個(gè)濱河市挺邀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖端铛,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泣矛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡禾蚕,警方通過(guò)查閱死者的電腦和手機(jī)您朽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)换淆,“玉大人哗总,你說(shuō)我怎么就攤上這事”妒裕” “怎么了讯屈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)县习。 經(jīng)常有香客問(wèn)我耻煤,道長(zhǎng),這世上最難降的妖魔是什么准颓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮棺妓,結(jié)果婚禮上攘已,老公的妹妹穿的比我還像新娘。我一直安慰自己怜跑,他們只是感情好样勃,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著性芬,像睡著了一般峡眶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上植锉,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天辫樱,我揣著相機(jī)與錄音,去河邊找鬼俊庇。 笑死狮暑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辉饱。 我是一名探鬼主播搬男,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼彭沼!你這毒婦竟也來(lái)了缔逛?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎褐奴,沒(méi)想到半個(gè)月后按脚,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡歉糜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年乘寒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匪补。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡伞辛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出夯缺,到底是詐尸還是另有隱情蚤氏,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布踊兜,位于F島的核電站竿滨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捏境。R本人自食惡果不足惜于游,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望垫言。 院中可真熱鬧贰剥,春花似錦、人聲如沸筷频。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)凛捏。三九已至担忧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坯癣,已是汗流浹背瓶盛。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留示罗,地道東北人蓬网。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鹉勒,于是被迫代替她去往敵國(guó)和親帆锋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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