在 Go 語言的 GMP 模型中,調度器負責將 goroutine 分配到不同的 P(Processor)上執行。當本地的 goroutine 隊列(稱為 LRQ,Local Run Queue)為空時,P 會嘗試從全局的 goroutine 隊列(稱為 GQ,Global Run Queue)中獲取 goroutine 來執行。為了平衡負載和效率,Go 調度器使用了一個公式來決定從全局隊列中一次取多少個 goroutine 到本地隊列。
這個公式是:
$$ n = \min\left(\frac{\text{len(GQ)}}{\text{GOMAXPROCS}} + 1, \frac{\text{len(GQ)}}{2}\right) $$
下面是對這個公式的詳細解釋:
-
GOMAXPROCS:這是 Go 程序運行時的一個環境變量或參數,它指定了程序可以同時使用的最大 CPU 核心數(即 P 的數量)。這個值可以通過
runtime.GOMAXPROCS(n int)函數來設置,如果不設置,默認值是機器的 CPU 核心數。 -
len(GQ):這是全局 goroutine 隊列中當前待執行的 goroutine 的數量。
-
$\frac{\text{len(GQ)}}{\text{GOMAXPROCS}} + 1$:這部分的意思是,將全局隊列中的 goroutine 均勻地分配給每個 P,然后再加 1。加 1 的目的是為了確保即使全局隊列中的 goroutine 數量很少,每個 P 也能至少獲取到一個 goroutine,從而避免饑餓問題。
-
$\frac{\text{len(GQ)}}{2}$:這部分是一個限制,意味著一次從一個 P 試圖從全局隊列中獲取 goroutine 的數量不會超過全局隊列中 goroutine 總數的一半。這是為了防止一個 P 一次性取走太多 goroutine,導致其他 P 長時間無法獲取到工作,從而保持系統的負載均衡。
-
$\min(...)$:最終取這兩個計算結果中的較小值,作為一次從全局隊列中取走的 goroutine 的數量。這樣做既考慮了負載均衡,又考慮了效率,確保每個 P 都能有效地獲取到工作,同時避免單個 P 負擔過重。
綜上所述,這個公式旨在平衡 Go 程序中 goroutine 的分配,確保所有 P 都能有效地獲取到工作,同時避免任何 P 過載或饑餓。通過動態調整從全局隊列中獲取 goroutine 的數量,Go 調度器能夠有效地利用多核 CPU 的性能,提高程序的執行效率。
本文來自博客園,作者:del88,轉載請注明原文鏈接:http://www.rzrgm.cn/del88/p/18593446
浙公網安備 33010602011771號