0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

詳解剖析Go語言調度模型的設計

馬哥Linux運維 ? 來源:愛戶外的程序猿 ? 作者:愛戶外的程序猿 ? 2021-07-26 10:12 ? 次閱讀

golang的MPG調度模型是保障Go語言效率高的一個重要特性,本文詳細介紹了Go語言調度模型的設計。

前言

Please remember that at the end of the day, all programs that work on UNIX machines end up using C system calls to communicate with the UNIX kernel and perform most of their tasks. 所有在 UNIX 系統(tǒng)上運行的程序最終都會通過 C 系統(tǒng)調用來和內(nèi)核打交道。

用其他語言編寫程序進行系統(tǒng)調用,方法不外乎兩個:一是自己封裝,二是依賴 glibc、或者其他的運行庫。Go 語言選擇了前者,把系統(tǒng)調用都封裝到了 syscall 包。封裝時也同樣得通過匯編實現(xiàn)。

異步系統(tǒng)調用 G 會和MP分離(G掛到netpoller),同步系統(tǒng)調用 GM 會和P分離(P另尋M),生動的說明了GPM相對GM的精妙之處。

阻塞

在 Go 里面阻塞主要分為以下 4 種場景:

由于原子、互斥量或通道操作調用導致 Goroutine 阻塞,調度器將把當前阻塞的 Goroutine 切換出去,重新調度 LRQ 上的其他 Goroutine;

由于網(wǎng)絡請求和 IO 操作導致 Goroutine 阻塞。Go 程序提供了網(wǎng)絡輪詢器(NetPoller)來處理網(wǎng)絡請求和 IO 操作的問題,其后臺通過 kqueue(MacOS),epoll(Linux)或 iocp(Windows)來實現(xiàn) IO 多路復用。通過使用 NetPoller 進行網(wǎng)絡系統(tǒng)調用,調度器可以防止 Goroutine 在進行這些系統(tǒng)調用時阻塞 M。

這可以讓 M 執(zhí)行 P 的 LRQ 中其他的 Goroutines,而不需要創(chuàng)建新的 M。執(zhí)行網(wǎng)絡系統(tǒng)調用不需要額外的 M,網(wǎng)絡輪詢器使用系統(tǒng)線程,它時刻處理一個有效的事件循環(huán),有助于減少操作系統(tǒng)上的調度負載。

用戶層眼中看到的 Goroutine 中的“block socket”,實現(xiàn)了 goroutine-per-connection 簡單的網(wǎng)絡編程模式。實際上是通過 Go runtime 中的 netpoller 通過 Non-block socket + I/O 多路復用機制“模擬”出來的。

當調用一些系統(tǒng)方法的時候(如文件 I/O),如果系統(tǒng)方法調用的時候發(fā)生阻塞,這種情況下,網(wǎng)絡輪詢器(NetPoller)無法使用,而進行系統(tǒng)調用的 G1 將阻塞當前 M1。調度器引入 其它M 來服務 M1 的P。

如果在 Goroutine 去執(zhí)行一個 sleep 操作,導致 M 被阻塞了。Go 程序后臺有一個監(jiān)控線程 sysmon,它監(jiān)控那些長時間運行的 G 任務然后設置可以強占的標識符,別的 Goroutine 就可以搶先進來執(zhí)行。

系統(tǒng)調用

Go 語言通過 Syscall 和 Rawsyscall 等使用匯編語言編寫的方法封裝了操作系統(tǒng)提供的所有系統(tǒng)調用,其中 Syscall 在 Linux 386 上的實現(xiàn)如下:

TEXT ·Syscall(SB),NOSPLIT,$0-28

CALL runtime·entersyscall(SB)

MOVL trap+0(FP), AX // syscall entry

MOVL a1+4(FP), BX

MOVL a2+8(FP), CX

MOVL a3+12(FP), DX

MOVL $0, SI

MOVL $0, DI

INVOKE_SYSCALL

CMPL AX, $0xfffff001

JLS ok

MOVL $-1, r1+16(FP)

MOVL $0, r2+20(FP)

NEGL AX

MOVL AX, err+24(FP)

CALL runtime·exitsyscall(SB)

RET

ok:

MOVL AX, r1+16(FP)

MOVL DX, r2+20(FP)

MOVL $0, err+24(FP)

CALL runtime·exitsyscall(SB)

RET

Golang - 調度剖析 https://segmentfault.com/a/1190000016611742

Go: Goroutine, OS Thread and CPU Management https://medium.com/a-journey-with-go/go-goroutine-os-thread-and-cpu-management-2f5a5eaf518a

Go optimizes the system calls — whatever it is blocking or not — by wrapping them up in the runtime. This wrapper will automatically dissociate the P from the thread M and allow another thread to run on it.

異步系統(tǒng)調用

通過使用網(wǎng)絡輪詢器進行網(wǎng)絡系統(tǒng)調用,調度器可以防止 Goroutine 在進行這些系統(tǒng)調用時阻塞M。這可以讓M執(zhí)行P的 LRQ 中其他的 Goroutines,而不需要創(chuàng)建新的M。有助于減少操作系統(tǒng)上的調度負載。

G1正在M上執(zhí)行,還有 3 個 Goroutine 在 LRQ 上等待執(zhí)行

接下來,G1想要進行網(wǎng)絡系統(tǒng)調用,因此它被移動到網(wǎng)絡輪詢器并且處理異步網(wǎng)絡系統(tǒng)調用。然后,M可以從 LRQ 執(zhí)行另外的 Goroutine。

最后:異步網(wǎng)絡系統(tǒng)調用由網(wǎng)絡輪詢器完成,G1被移回到P的 LRQ 中。一旦G1可以在M上進行上下文切換,它負責的 Go 相關代碼就可以再次執(zhí)行。

同步系統(tǒng)調用

G1將進行同步系統(tǒng)調用以阻塞M1

調度器介入后:識別出G1已導致M1阻塞,此時,調度器將M1與P分離,同時也將G1帶走。然后調度器引入新的M2來服務P。

b030aa1a-db82-11eb-9e57-12bb97331649.png

阻塞的系統(tǒng)調用完成后:G1可以移回 LRQ 并再次由P執(zhí)行。如果這種情況需要再次發(fā)生,M1將被放在旁邊以備將來使用。

b03e4c56-db82-11eb-9e57-12bb97331649.png

sysmon 協(xié)程

b04936ca-db82-11eb-9e57-12bb97331649.jpg

在 linux 內(nèi)核中有一些執(zhí)行定時任務的線程, 比如定時寫回臟頁的 pdflush, 定期回收內(nèi)存的 kswapd0, 以及每個 cpu 上都有一個負責負載均衡的 migration 線程等。在 go 運行時中也有類似的協(xié)程 sysmon. sysmon 運行在 M,且不需要 P。它會每隔一段時間檢查 Go 語言runtime,確保程序沒有進入異常狀態(tài)。

系統(tǒng)監(jiān)控的觸發(fā)時間就會穩(wěn)定在 10ms,功能比較多:

檢查死鎖runtime.checkdead

運行計時器 — 獲取下一個需要被觸發(fā)的計時器;

定時從 netpoll 中獲取 ready 的協(xié)程

Go 的搶占式調度

當 sysmon 發(fā)現(xiàn) M 已運行同一個 G(Goroutine)10ms 以上時,它會將該 G 的內(nèi)部參數(shù) preempt 設置為 true。然后,在函數(shù)序言中,當 G 進行函數(shù)調用時,G 會檢查自己的 preempt 標志,如果它為 true,則它將自己與 M 分離并推入“全局隊列”。由于它的工作方式(函數(shù)調用觸發(fā)),在 for{} 的情況下并不會發(fā)生搶占,如果沒有函數(shù)調用,即使設置了搶占標志,也不會進行該標志的檢查。

Go1.14 引入搶占式調度(使用信號的異步搶占機制),sysmon 仍然會檢測到運行了 10ms 以上的 G(goroutine)。然后,sysmon 向運行 G 的 P 發(fā)送信號(SIGURG)。Go 的信號處理程序會調用P上的一個叫作 gsignal 的 goroutine 來處理該信號,將其映射到 M 而不是 G,并使其檢查該信號。gsignal 看到搶占信號,停止正在運行的 G。

在滿足條件時觸發(fā)垃圾收集回收內(nèi)存;

打印調度信息,歸還內(nèi)存等定時任務。

轉自:bert.li@ximalaya.com

qiankunli.github.io/2020/11/21/goroutine_system_call.html

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • go語言
    +關注

    關注

    1

    文章

    156

    瀏覽量

    8996

原文標題:Golang 系統(tǒng)調用與阻塞處理

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    三十分鐘入門基礎Go Java小子版

    前言 Go語言定義 Go(又稱 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 開發(fā)的一種靜態(tài)、強類型、編譯型語言
    的頭像 發(fā)表于 08-12 14:32 ?590次閱讀
    三十分鐘入門基礎<b class='flag-5'>Go</b> Java小子版

    語言模型(LLM)快速理解

    自2022年,ChatGPT發(fā)布之后,大語言模型(LargeLanguageModel),簡稱LLM掀起了一波狂潮。作為學習理解LLM的開始,先來整體理解一下大語言模型。一、發(fā)展歷史大
    的頭像 發(fā)表于 06-04 08:27 ?667次閱讀
    大<b class='flag-5'>語言</b><b class='flag-5'>模型</b>(LLM)快速理解

    語言模型:原理與工程時間+小白初識大語言模型

    解鎖 我理解的是基于深度學習,需要訓練各種數(shù)據(jù)知識最后生成自己的的語言理解和能力的交互模型。 對于常說的RNN是處理短序列的數(shù)據(jù)時表現(xiàn)出色,耳真正厲害的是Transformer,此框架被推出后直接
    發(fā)表于 05-12 23:57

    【大語言模型:原理與工程實踐】大語言模型的應用

    ,它通過抽象思考和邏輯推理,協(xié)助我們應對復雜的決策。 相應地,我們設計了兩類任務來檢驗大語言模型的能力。一類是感性的、無需理性能力的任務,類似于人類的系統(tǒng)1,如情感分析和抽取式問答等。大語言
    發(fā)表于 05-07 17:21

    【大語言模型:原理與工程實踐】大語言模型的評測

    語言模型的評測是確保模型性能和應用適應性的關鍵環(huán)節(jié)。從基座模型到微調模型,再到行業(yè)模型和整體能
    發(fā)表于 05-07 17:12

    【大語言模型:原理與工程實踐】探索《大語言模型原理與工程實踐》2.0

    《大語言模型“原理與工程實踐”》是關于大語言模型內(nèi)在機理和應用實踐的一次深入探索。作者不僅深入討論了理論,還提供了豐富的實踐案例,幫助讀者理解如何將理論知識應用于解決實際問題。書中的案
    發(fā)表于 05-07 10:30

    【大語言模型:原理與工程實踐】大語言模型的基礎技術

    全面剖析語言模型的核心技術與基礎知識。首先,概述自然語言的基本表示,這是理解大語言模型技術的
    發(fā)表于 05-05 12:17

    【大語言模型:原理與工程實踐】揭開大語言模型的面紗

    語言模型(LLM)是人工智能領域的尖端技術,憑借龐大的參數(shù)量和卓越的語言理解能力贏得了廣泛關注。它基于深度學習,利用神經(jīng)網(wǎng)絡框架來理解和生成自然語言文本。這些
    發(fā)表于 05-04 23:55

    【大語言模型:原理與工程實踐】探索《大語言模型原理與工程實踐》

    《大語言模型》是一本深入探討人工智能領域中語言模型的著作。作者通過對語言模型的基本概念、基礎技術
    發(fā)表于 04-30 15:35

    Go語言中的函數(shù)、方法與接口詳解

    Go 沒有類,不過可以為結構體類型定義方法。方法就是一類帶特殊的接收者參數(shù)的函數(shù)。方法接收者在它自己的參數(shù)列表內(nèi),位于 func 關鍵字和方法名之間。(非結構體類型也可以定義方法)
    的頭像 發(fā)表于 04-23 16:21 ?609次閱讀

    語言模型概述

    在科技飛速發(fā)展的當今時代,人工智能技術成為社會進步的關鍵推動力之一。在廣泛關注的人工智能領域中,大語言模型以其引人注目的特性備受矚目。 大語言模型的定義及發(fā)展歷史 大
    的頭像 發(fā)表于 12-21 17:53 ?1277次閱讀

    Go編程語言-你應該知道的一切

    Go 編程語言的故事始于 Google,當時三位工程師 Robert Griesemer、Rob Pike 和 Ken Thompson 對 C++ 的復雜性以及缺乏提供高效編譯和執(zhí)行的簡單語言感到厭倦。
    的頭像 發(fā)表于 12-11 17:37 ?492次閱讀

    語言模型簡介:基于大語言模型模型全家桶Amazon Bedrock

    本文基于亞馬遜云科技推出的大語言模型與生成式AI的全家桶:Bedrock對大語言模型進行介紹。大語言模型
    的頭像 發(fā)表于 12-04 15:51 ?648次閱讀

    Go語言比Python強多少

    1.都說Go語言性能非常強大,那么到底比Python強多少? 為了比較Go語言和Python語言在單線程性能上的差距,我們可以做一個簡單實驗
    的頭像 發(fā)表于 11-02 14:05 ?441次閱讀
    <b class='flag-5'>Go</b><b class='flag-5'>語言</b>比Python強多少

    如何讓Python和Go互相調度

    我們曾經(jīng)研究過如何讓Python和Go互相調度,當時發(fā)現(xiàn),將Go語言寫的模塊打包成動態(tài)鏈接庫,就能在Python中進行調度: 優(yōu)劣互補! P
    的頭像 發(fā)表于 11-02 11:24 ?461次閱讀
    如何讓Python和<b class='flag-5'>Go</b>互相<b class='flag-5'>調度</b>