GOMAXPROCS 是 Go 提供的很是重要的一個環境變量。經過設定 GOMAXPROCS,用戶能夠調整調度器中 Processor(簡稱P)的數量。因爲每一個系統線程必需要綁定 P ,P 才能把 G 交給 M 執行。以下圖所示微信
因此 P 的數量會很大程度上影響 Go Runtime 的並發表現。GOMAXPROCS 在 Go 1.5 版本後的默認值是機器的 CPU 核數 (runtime.NumCPU)。經過下面的代碼片斷能夠獲取當前機器的核心數和給 GOMAXPROCS 設置的值。markdown
package main
import (
"fmt"
"runtime"runtimego" ) func getGOMAXPROCS() int { _ := runtime.NumCPU() // 獲取機器的CPU核心數 return runtime.GOMAXPROCS(0) // 參數爲零時用於獲取給GOMAXPROCS設置的值 } func main() { fmt.Printf("GOMAXPROCS: %d\n", getGOMAXPROCS()) } 複製代碼
而以 Docker 爲表明的容器虛擬化技術,會經過 cgroup 等技術對 CPU 資源進行隔離。以 Kubernetes 爲表明的基於容器虛擬化實現的資源管理系統,也支持這樣的特性,好比下面這個 PodTemplate 的容器的定義裏 limits.cpu = 1000m 就表明給這個容器分配1個核心的使用時間。併發
這類技術對 CPU 的隔離限制,致使 runtime.NumCPU()
沒法正確獲取到容器被分配的 CPU 資源數。runtime.NumCPU()
獲取的是宿主機的核心數。app
設置 GOMAXPROCS 高於真正可以使用的核心數後會致使Go調度器不停地進行OS線程切換,從而給調度器增長不少沒必要要的工做。oop
目前 Go 官方並沒有好的方式來規避在容器裏獲取不到真正可以使用的核心數這一問題,而 Uber 提出了一種 Workaround 方法,利用 uber-go/automaxprocs 這一個包,能夠在運行時根據 cgroup 爲容器分配的CPU資源限制數來修改 GOMAXPROCS。spa
import _ "go.uber.org/automaxprocs"
func main() {
// Your application logic here.
}
複製代碼
參考資料:線程
stackoverflow.com/questions/3…code
GMP調度器orm
今天的文章就到這裏啦,若是喜歡個人文章就幫我點個贊吧,我會每週經過技術文章分享個人所學所見和第一手實踐經驗,感謝你的支持。微信搜索關注公衆號「網管叨bi叨」每週教會你一個進階知識。