<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          「Go實(shí)戰(zhàn)系列」Go 語(yǔ)言中的一些非常規(guī)優(yōu)化

          共 2195字,需瀏覽 5分鐘

           ·

          2021-08-29 06:28

          這次去 Gopher China 和不少老朋友見(jiàn)了個(gè)面,還有不少在微信上認(rèn)識(shí)已久,一直沒(méi)見(jiàn)過(guò)面的網(wǎng)友。同時(shí)也和各個(gè)公司的一線(xiàn)開(kāi)發(fā)們聊了聊,互相交流了彼此使用 Go 時(shí)的一些心得和痛點(diǎn)。

          綜合近期了解的一些相關(guān)分享,我把到目前為止見(jiàn)到的,不那么常見(jiàn)的,各方對(duì) Go 的優(yōu)化和 hack 集中在這篇文章里。因?yàn)榭紤]到一些公司情況比較特殊,所以本文中列出的點(diǎn)就不標(biāo)記是哪個(gè)公司做的了。未來(lái)他們覺(jué)得時(shí)機(jī)成熟應(yīng)該也會(huì)自己出來(lái)做一些分享。

          01

          網(wǎng)絡(luò)方面


          當(dāng)前 Go 的網(wǎng)絡(luò)抽象在效率上有些低,每一個(gè)連接至少要有一個(gè) goroutine 來(lái)維護(hù),有些協(xié)議實(shí)現(xiàn)可能有兩個(gè)。因此 goroutine 總數(shù) = 連接數(shù) * 1 or 連接數(shù) * 2。當(dāng)連接數(shù)超過(guò) 10w 時(shí),goroutine 棧本身帶來(lái)的內(nèi)存消耗就有幾個(gè) GB。

          大量的 goroutine 也會(huì)給調(diào)度和 GC 均帶來(lái)很大壓力。Go 底層的網(wǎng)絡(luò)庫(kù)和加密庫(kù)效率也不是很高,所以在同類(lèi)應(yīng)用上和 C++ 等語(yǔ)言有較大性能差距(內(nèi)存、吞吐量)。

          社區(qū)有不少使用裸調(diào) Epoll 實(shí)現(xiàn)優(yōu)化的庫(kù),就不給他們打廣告了。由于用戶(hù)的 syscall.EpollWait 是運(yùn)行在一個(gè)沒(méi)有任何優(yōu)先級(jí)的 goroutine 中,當(dāng) CPU idle 較低時(shí),系統(tǒng)整體的延遲不可控,比標(biāo)準(zhǔn)庫(kù)的延遲還要高很多。之前個(gè)人做過(guò)相關(guān)的測(cè)試,核心數(shù)的增加也會(huì)使系統(tǒng)相應(yīng)的延遲大幅上升。

          接下來(lái)不同的公司的優(yōu)化思路就走向了兩個(gè)方向:

          1. 修改 runtime,在 runtime 增加用戶(hù) Epoll 函數(shù)的回調(diào)。類(lèi)似 runtime 自己實(shí)現(xiàn)的 netpoll 那樣。這種方式會(huì)導(dǎo)致 Go 本身難以升級(jí),必須跟著有 hack 的版本走。當(dāng)遇到 Go 的 bug 時(shí)會(huì)比較尷尬。
          2. 把 c 實(shí)現(xiàn)的網(wǎng)絡(luò)庫(kù)當(dāng)作基礎(chǔ)組件,把 Go 實(shí)現(xiàn)的業(yè)務(wù)邏輯作為業(yè)務(wù)嫁接在 c 庫(kù)之上。

          Go 語(yǔ)言的強(qiáng)項(xiàng)就是在網(wǎng)絡(luò)編程上,現(xiàn)在卻逼得大家為了優(yōu)化都需要去做對(duì) runtime 的 hack,甚至嫁接其它語(yǔ)言,這不能不說(shuō)有點(diǎn)悲哀。還是希望未來(lái)官方能夠有更好的底層基礎(chǔ)工具來(lái)支持這種超高連接數(shù)的場(chǎng)景。

          02

          cgo

          因?yàn)?c 歷史悠久,所以對(duì) cgo 的使用是難以避免的,個(gè)人見(jiàn)到比較多的,比如做國(guó)際化需求必須要用到的 icu 庫(kù),只能用 cgo 來(lái)調(diào)。或者做 cv 的 opencv,也只能用 cgo?;蛘邍?guó)密場(chǎng)景,也只能用 cgo。

          但從 go 調(diào)用到 c,有一次棧切換,成本有些高,所以有公司實(shí)現(xiàn)了從 go 切換到 c 不需要切換棧的神奇調(diào)用方式,同時(shí)在棧上打標(biāo)記,讓 GC 只掃描 Go 的棧而不掃描 c 的棧。

          03

          go-plugin

          官方提供的 go plugin 還是比較難用的,比如要求編譯版本必須統(tǒng)一;加載后無(wú)法卸載等。

          現(xiàn)在有公司基于 .got 表,實(shí)現(xiàn)了比官方的 plugin 更靈活的熱加載,熱卸載的動(dòng)態(tài)庫(kù)。

          (這條我不太懂,所以只是聽(tīng)說(shuō),有問(wèn)題歡迎指出

          04

          匯編優(yōu)化

          Go 語(yǔ)言的編譯后端都是 Go 自己實(shí)現(xiàn)的,沒(méi)有借助以往的平臺(tái),如 LLVM。

          有人將 C 語(yǔ)言編寫(xiě)的等價(jià)代碼用較高的優(yōu)化級(jí)別,如 clang -o3,編譯為高度優(yōu)化的匯編,再翻譯為 plan9 匯編,整合成函數(shù)供 Go 應(yīng)用調(diào)用,這樣相當(dāng)于在 Go 里享受了 llvm 平臺(tái)的后端優(yōu)化成果。

          05

          runtime 修改

          除了前面提到的網(wǎng)絡(luò)編程時(shí),epollwait 需要高優(yōu)先級(jí)的 goroutine,在其它一些涉及到任務(wù)分發(fā),任務(wù)處理的應(yīng)用程序中也需要類(lèi)似的高優(yōu)先級(jí) goroutine。

          所以有公司直接在 runtime 提供了接口,讓用戶(hù)可以通過(guò)接口來(lái)創(chuàng)建特殊優(yōu)先級(jí)的 goroutine。

          除了暴露接口外,對(duì) runtime 的實(shí)現(xiàn)代碼也是要做不少修改的。

          06

          通過(guò) SSA 進(jìn)行的靜態(tài)檢查

          我們知道,當(dāng)前社區(qū)的 golangci-lint 大多是用 Go 內(nèi)置的編譯前端來(lái)完成的,在編譯后的 ast 上做一些邏輯,來(lái)提示用戶(hù)代碼中可能存在的問(wèn)題。

          在一些較底層的編程場(chǎng)景,希望能夠消滅所有的堆分配,所以他們通過(guò)檢查生成的 SSA 中是否有 newobject 的調(diào)用來(lái)輔助進(jìn)行代碼的優(yōu)化。

          07

          垃圾回收

          Go 語(yǔ)言的垃圾回收沒(méi)有分代,分代會(huì)涉及到不同代際之間的對(duì)象移動(dòng),從 Go 官方歷史上的分享來(lái)看,Go 的開(kāi)發(fā)者們對(duì) non-moving 比較執(zhí)著。因?yàn)槿绻焉蠈?duì)象會(huì) move 的話(huà),需要在讀對(duì)象時(shí)開(kāi)啟 read barrier,幾乎所有場(chǎng)景都是讀多寫(xiě)少的場(chǎng)景,這樣會(huì)極大影響程序性能,所以官方現(xiàn)在在分代的研發(fā)上處于停滯狀態(tài)。

          國(guó)內(nèi)某公司在之前官方分代 GC CL 的基礎(chǔ)上實(shí)現(xiàn)了分代垃圾回收,不過(guò)因?yàn)榭床坏酱a,不太清楚他們最終在生產(chǎn)環(huán)境是否能夠達(dá)到較好的性能改善。

          08

          總結(jié)

          未來(lái)如果發(fā)現(xiàn)更多值得一聊的優(yōu)化的話(huà),也許會(huì)寫(xiě)個(gè)續(xù)。

          本篇中的內(nèi)容都是簡(jiǎn)單的介紹,沒(méi)有太多細(xì)節(jié),如果感興趣的讀者比較多的話(huà),我們后續(xù)把每一點(diǎn)都展開(kāi)來(lái)講講~


          想要獲取實(shí)戰(zhàn)營(yíng)的相關(guān)信息,請(qǐng)掃碼進(jìn)群哦~


          如果群滿(mǎn),可加小助手,就能拉你一起加入群聊啦




          瀏覽 44
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五月涩欧美| 麻豆久久艹 | 免费观看一级二级网站 | 男人的天堂青青草 | 国产精品久久久久久最猛 |