<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 運(yùn)行時調(diào)度器處理系統(tǒng)調(diào)用的巧妙方式

          共 2634字,需瀏覽 6分鐘

           ·

          2020-10-08 10:38

          點(diǎn)擊上方藍(lán)色“Go語言中文網(wǎng)”關(guān)注,回復(fù)「電子書」領(lǐng)全套Go資料

          goroutine[1] 是 Go 的一個標(biāo)志性特點(diǎn),是被 Go 運(yùn)行時所管理的輕量線程。Go 運(yùn)行時使用一個 M:N 工作竊取調(diào)度器[2]實(shí)現(xiàn) goroutine,將 Goroutine 復(fù)用在操作系統(tǒng)線程上。調(diào)度器有著特殊的術(shù)語用來描述三個重要的實(shí)體;G 是 goroutine,M 是 OS 線程(一個“機(jī)器 machine”),P 是“處理器(processor)”,它的核心是有限的資源,而 M 需要這些資源來運(yùn)行 Go 代碼。限制 P 的供應(yīng)是 Go 用來限制一次執(zhí)行多少操作以避免整個系統(tǒng)超載的手段。通常來說,每個 OS 所報(bào)告的實(shí)際的 CPU 有一個對應(yīng)的 P (P 的數(shù)量是 GOMAXPROCS[3])。

          當(dāng) Goroutine 執(zhí)行 網(wǎng)絡(luò) IO 或者任何覺得可以異步完成的系統(tǒng)調(diào)用操作時,Go 有一個完整的運(yùn)行時子系統(tǒng),netpoller[4],(使用類似 epoll[5] 的系統(tǒng)調(diào)用機(jī)制)將看起來像多個單獨(dú)的同步操作轉(zhuǎn)換為一個單獨(dú)的等待。goroutine 并沒有真正進(jìn)行阻塞的系統(tǒng)調(diào)用,而是像等待一個 channel 就緒那樣進(jìn)入休眠狀態(tài)等待其網(wǎng)絡(luò)套接字。如果很難有效地實(shí)現(xiàn),概念上講這些都是直白的。

          無論如何,網(wǎng)絡(luò) IO 以及類似的東西遠(yuǎn)不是 Go 程序可以處理的唯一的系統(tǒng)調(diào)用,因此 Go 也必須處理阻塞的系統(tǒng)調(diào)用。對 Goroutine 的 M 來說,處理阻塞的系統(tǒng)調(diào)用的直接方式是在系統(tǒng)調(diào)用前釋放 P ,并且在系統(tǒng)調(diào)用恢復(fù)后嘗試重新獲取 P 。如果那時候沒有空閑的 P ,goroutine 會隨著其他等待運(yùn)行的任務(wù)被停放在調(diào)度器中。

          雖然理論上所有的系統(tǒng)調(diào)用都是阻塞的,在實(shí)踐中不是所有的調(diào)用都會阻塞。例如,在現(xiàn)代系統(tǒng)中,獲取當(dāng)前時間的“系統(tǒng)調(diào)用”可能甚至沒有進(jìn)入內(nèi)核(見 Linux 的 vdso(7)[6])。讓 Goroutine 完成釋放他們當(dāng)前的 P 的全部工作再為了這些系統(tǒng)調(diào)用重新獲取一個 P 有兩個問題:首先,所有涉及到的數(shù)據(jù)結(jié)構(gòu)的鎖定(和釋放)有著很大的開銷。其次,如果可運(yùn)行的 Goroutine 比 P 多,進(jìn)行這類系統(tǒng)調(diào)用的 Goroutine 無法重新獲取 P 并且不得不把自己停放;釋放 P 的瞬間,其他 Goroutine 就會被調(diào)度到上面。這是額外的運(yùn)行時開銷,有點(diǎn)不公平,并且不利于進(jìn)行快速系統(tǒng)調(diào)度的目的(尤其是那些不進(jìn)入內(nèi)核的調(diào)用)。

          所以 Go 運(yùn)行時和調(diào)度器實(shí)際上有兩種處理阻塞系統(tǒng)調(diào)用的方法,一種悲觀方式,應(yīng)用于預(yù)計(jì)會很慢的系統(tǒng)調(diào)用;另一種樂觀方式,應(yīng)用于預(yù)計(jì)會很快的系統(tǒng)調(diào)用。悲觀的系統(tǒng)調(diào)用路徑實(shí)現(xiàn)了直接的方法,運(yùn)行時在系統(tǒng)調(diào)用前主動釋放 P,之后嘗試將 P 找回來,如果無法獲取則停放自身。樂觀的系統(tǒng)調(diào)用路徑不會釋放 P,相反,會設(shè)置一個特殊的 P 的狀態(tài)標(biāo)識并繼續(xù)進(jìn)行系統(tǒng)調(diào)用。一個特殊的內(nèi)部 goroutine,sysmon goroutine,定期執(zhí)行并尋找設(shè)置了這個“進(jìn)行系統(tǒng)調(diào)用中”狀態(tài)的時間太長了的 P,并將 P 從進(jìn)行系統(tǒng)調(diào)用的 Goroutine 那里偷走。當(dāng)系統(tǒng)調(diào)用返回,運(yùn)行時代碼檢查它的 P 是否被偷走,如果沒有則繼續(xù)執(zhí)行(如果 P 被偷走了的話,運(yùn)行時會嘗試獲取其他的 P,如果失敗可能會停放 goroutine)。

          如果一切順利,樂觀的系統(tǒng)調(diào)用路徑有著非常低的開銷(大多數(shù)情況下,需要幾個原子比較和交換[7]操作)。如果不順利并且可運(yùn)行的 Goroutine 的數(shù)量比 P 多,一個 P 會有不必要的空閑,通常可能是數(shù)十微秒(sysmon Goroutine 最多每 20 微秒運(yùn)行一次,但如果似乎沒有必要的話可以減少運(yùn)行頻率)。可能存在著最壞的情況,但是一般來說,在 Go 運(yùn)行時方面這是一個值得的抉擇。


          via: https://utcc.utoronto.ca/~cks/space/blog/programming/GoSchedulerAndSyscalls

          作者:ChrisSiebenmann[8]譯者:dust347[9]校對:JYSDeveloper[10]

          本文由 GCTT[11] 原創(chuàng)編譯,Go 中文網(wǎng)[12] 榮譽(yù)推出

          參考資料

          [1]

          goroutine: https://tour.golang.org/concurrency/1

          [2]

          一個 M:N 工作竊取調(diào)度器: https://rakyll.org/scheduler/

          [3]

          GOMAXPROCS: https://golang.org/pkg/runtime/

          [4]

          netpoller: https://morsmachine.dk/netpoller

          [5]

          epoll: https://medium.com/@copyconstruct/the-method-to-epolls-madness-d9d2d6378642

          [6]

          vdso(7): http://man7.org/linux/man-pages/man7/vdso.7.html

          [7]

          原子比較和交換: https://en.wikipedia.org/wiki/Compare-and-swap

          [8]

          ChrisSiebenmann: https://twitter.com/thatcks/

          [9]

          dust347: https://github.com/dust347

          [10]

          JYSDeveloper: https://github.com/JYSDeveloper

          [11]

          GCTT: https://github.com/studygolang/GCTT

          [12]

          Go 中文網(wǎng): https://studygolang.com/



          推薦閱讀


          福利

          我為大家整理了一份從入門到進(jìn)階的Go學(xué)習(xí)資料禮包(下圖只是部分),同時還包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。

          關(guān)注公眾號 「polarisxu」,回復(fù) ebook 獲取;還可以回復(fù)「進(jìn)群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。


          瀏覽 47
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  国产黄色视频大全 | 国产久久熟女拳交免费视频 | 精品九色| 久久伊人视频 | 久久久久亚洲AV成人网址老师板 |