golang中GPM模型原理與排程器設計策略
阿新 • • 發佈:2021-11-11
一、GMP模型原理first:
1. 全域性佇列:存放待執行的G
2. P的本地佇列:同全域性佇列類似,存放待執行的G,儲存的數量有限:256個,
當建立新的G‘時,G’優先加入到P的本地佇列,如果佇列已滿,會把P本地佇列中一半的G移動到全域性佇列
3. M執行緒:M執行G需要先獲取P,然後從P本地佇列中取G執行,如果P本地佇列為空,M會把全域性佇列中一批G移動到P本地佇列
或去其它P佇列中偷一半G到P本地佇列,M執行G,G執行完後,M會從P獲取下一個G,不斷重複執行
4. P列表:所有的P都在程式啟動時建立,並儲存在陣列中,最多有GOMAXPROCS個
總結:goroutine排程器與OS執行緒排程器通過M結合起來,每一個M代表一個核心執行緒,OS排程器負責把核心執行緒分配到CPU上去執行
second:
有關 P 和 M 的數量問題
1. P 的數量:
由程式啟動時環境變數 $GOMAXPROCS 或 runtime方法GOMAXPROCS()決定,
這意味著在程式執行的任意時刻都只有 $MAXPROCS個goroutine在執行
2. M 的數量
2.1 go 語言本身的限制,go 程式啟動時會設定M的最大數量,預設10000,但是核心很難支援這麼多的執行緒,
所以可以忽略,
2.1 runtime/debug中的SetMaxThreads函式,設定 M 的最大數量
2.3 當一個M阻塞了,會建立新的M
3. M和P的數量沒有絕對關係,一個M阻塞,P就會建立或者切換其它的M,所以即使P的數量是1,也有可能創建出很多個M出來
three:
P 和 M 何時會被建立
1. P 何時建立:在確定了P的最大數量n後,runtime執行時系統會根據這個數量建立n個P
2. M 何時建立:沒有足夠的M來關聯P並執行其中可執行的G;比如此時所有的M都阻塞住了,
但是P中還有很多就緒任務,此時就會去建立新的M
二、排程器設計策略
1. 複用執行緒:避免重複的建立、銷燬執行緒,而是對執行緒的複用
work stealing機制:當本執行緒M無可執行的G時,會嘗試從其它執行緒繫結的P中偷取G,而不是銷燬執行緒
hand off機制:當本執行緒M因為G進行系統呼叫時阻塞,執行緒M釋放繫結的P,交給其它空閒的執行緒M去執行
利用並行:GOMAXPROCS設定P的數量,最多有GOMAXPROCS個執行緒分佈在多個CPU上執行,
GOMAXPROCS也限制了併發的程度,當設定 GOMAXPROCS = CPU核數/2 時,則最多利用了一半的CPU核進行並行
2. 搶佔:在coroutine中要等待一個協程讓出CPU才執行下一個協程,而在go中,一個goroutine最多佔用CPU 10ms,
防止其它goroutine被餓死,這就是goroutine不同於其它coroutine的區別
3. 全域性G佇列,在新的排程器中依然有全域性G佇列,但是功能被弱化了,當M執行 work stealing 從其它P佇列偷不到G時,
它可以從全域性G佇列獲取G
三、go func 排程流程
1. 我們通過 go func() 來建立一個 goroutine
2. 有兩個儲存G的佇列,一個是區域性排程器P的本地佇列,一個是全域性G佇列,新建立的G會先儲存在P的本地佇列中
如果P的本地佇列已滿就會儲存在全域性佇列中
3. G只能執行在M中,一個M必須持有一個P,M與P的關係時1:1,M先繫結P然後從P佇列中彈出一個可執行的G並執行,
如果P本地佇列為空,M會向其它MP組合偷取一個可執行的G執行
4. 一個M排程G執行的過程是一個迴圈機制
5. 當一個M執行一個G時發生了syscall或其它阻塞操作,M會阻塞,如果當前有一些G待執行,runtime會把這個執行緒M
從P中摘除,讓其它空餘的M執行緒(如果沒有就建立新的M執行緒)來服務於這個P
6. 當M系統呼叫結束的時候,這個G會嘗試獲取一個空閒的P,並放入到P的本地佇列中取,如果獲取不到P,
這個M執行緒變成休眠狀態,加入到空閒執行緒中去,然後這個G會被放入到全域性佇列中
四、排程器的宣告週期
M0: 是啟動程式後編號為0的主執行緒,M0負責初始化操作和執行第一個G,在之後M0就和其它M一樣了
G0: 是每次啟動M都會第一個建立的goroutine,GO僅用於負責排程的G,G0不指向任何可執行的函式,
每個M都會有一個自己的G0,在排程或系統呼叫時會使用G0的棧空間,
總結:go排程器的本質:把大量的goroutine分配到少量的執行緒上去執行,並利用多核並行,實現更強大的併發
參考連結:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/GMP%E5%8E%9F%E7%90%86%E4%B8%8E%E8%B0%83%E5%BA%A6.html