成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go Scheduler 的 GMP 模型

開發
Go 為了自身 goroutine 執行和調度的效率,自身在 runtime 中實現了一套 goroutine 的調度器。

寫在前面

Go 為了自身 goroutine 執行和調度的效率,自身在 runtime 中實現了一套 goroutine 的調度器,下面通過一段簡單的代碼展示一下 Go 應用程序在運行時的 goroutine,方便大家更好的理解。

The Go scheduler is part of the Go runtime, and the Go runtime is built into your application

for i := 0; i < 4; i++ {
go func() {
time.Sleep(time.Second)
}()
}
fmt.Println(runtime.NumGoroutine())

上面這段代碼的輸出為:5。說明當前這個應用程序中存在 goroutine 的數量是 5,事實上也符合我們的預期。那么問題來了,這 5 個 goroutine 作為操作系統用戶態的基本調度單元是無法直接占用操作系統的資源來執行的,必須經過內核級線程的分發,這是操作系統內部線程調度的基本模型,根據用戶級線程和內核級線程的對應關系可以分為 1 對 1,N 對 1 以及 M 對 N 這三種模型,那么上述的 5 個 goroutine 在內核級線程上是怎么被分發的,這就是 Go語言的 goroutine 調度器決定的。

圖片

GMP 模型

整個 goroutine 調度器的實現基于 GMP 的三級模型來實現。

  • G:goroutine
  • M:內核級線程,運行在操作系統的核心態。在 Go 中支持最大的 M 的數量是 10000,但是操作系統中通常情況是不可以創建這么多的線程。
  • P:processor,可以理解成一個等待分發給 M 調度執行的 goroutine 隊列。P的個數是由 runtime 的 GOMAXPROCS 來決定的。

M 和 P 存在一一對應的綁定關系。大致的結構圖如下所示:

圖片

goroutine 之旅

通常情況下,我們在代碼中執行 go func(){}后,GMP 模型是如何工作的?通過一個詳細的圖來展示一下。

圖片

  1. 首先創建一個新的 goroutine
  2. 如果本地的局部隊列中有足夠的空間可以存放,則放入局部隊列中;如果局部隊列滿,則放入一個全局隊列(所有的 M 都可以從全局隊列中拉取 G 來執行)
  3. 所有的 G 都必須在 M 上才可以被執行,M 和 P 存在一一綁定的關系,如果 M 綁定的 P 中存在可以被執行的 G,則從 P 中拉取 G 來執行;如果 P 中為空,沒有可執行的 G,則  M 從全局隊列中拉取;如果全局隊列也為空,則從其他的 P 中拉取 G
  4. 為 G 的運行分配必要的資源,等待 CPU 的調度
  5. 分配到 CPU,執行 func(){}

調度策略

整個 goroutine 調度器最重要的調度策略是:復用,避免頻繁的資源創建和銷毀,最大限度的提升系統的吞吐量和并發程度。這也是操作系統進行線程調度的終極目標。復用(reuse)也是很多「池化技術」的基礎。

圍繞著這一原則,goroutine 調度器在以下幾個方面進行調度策略的優化。

  1. 工作隊列的竊取機制:這個跟 Java 中的 ForkJoin Pool 的竊取機制同一原理,都是當線程 M 空閑時,從其他繁忙的隊列 P 中"竊取"任務 G 過來執行,而不是銷毀空閑的 M。因為線程的創建和銷毀是需要消耗系統資源的,避免線程的頻繁創建和銷毀可以極大的提升系統的并發程度。
  2. 交接機制:當線程M被阻塞的時候,M 會主動將 P 交接給其他空閑的 M。

另外,在 go 的 1.14 版本中,go 語言的技術團隊嘗試在調度器中添加了可搶占的技術[https://github.com/golang/go/issues/24543]

  1. 搶占技術的出現一方面解決了線程 M 在執行計算密集型任務時長時間占用 CPU,導致與之綁定的 P 上的其他 G 得不到執行而造成的"饑餓現象";
  2. 另一方面,搶占技術的出現對 GC 來講解決 GC 時可能出現的 deadLock,相關的 issue 見:關于 GC 時 tight loops 應該可以被搶占的討論
    [https://github.com/golang/go/issues/10958]

最開始的 MG 模型

在 go 語言的早期,goroutine 調度器的模型并不是 GMP,而是 GM。整個調度器維護一個全局的 G 的等待隊列,所有的 M 從這個全局的隊列中拉取 G 來執行,在 go1.1 中將這種模型直接干掉,取而代之的是現在的 GMP 模型,在 GM 模型的基礎上增加 P 局部隊列。官方之所有這么這么做,原因有二:

  1. 全局的 G 等待隊列,不同的M從隊列里取 G 都需要加鎖,鎖的粒度很大,嚴重制約了系統并發能力的提升;
  2. 沒有局部隊列,那么當線程在執行 IO 密集型操作時,M 阻塞在 IO 操作上,對應的 G 也沒有辦法得到執行(GMP 中可以將 G 交接給其他的 M 執行),因此 GM 模型在應對 IO 密集型任務時性能表現低下。
責任編輯:龐桂玉 來源: 字節跳動技術團隊
相關推薦

2024-07-30 12:24:23

2024-09-02 09:00:59

2023-05-22 09:27:11

GMPGolang

2023-08-21 07:34:37

GolangGMP

2021-10-26 07:42:49

Go線程數GMP

2022-12-06 08:30:06

SchedulerReact

2025-05-26 00:05:00

2023-03-06 00:27:02

Kubernetesscheduler系統

2021-07-06 14:47:30

Go 開發技術

2024-02-19 07:40:10

2021-06-02 09:23:57

Go開發內存

2024-06-27 07:56:49

2023-11-29 09:29:48

Kuberneteskube

2021-01-29 08:22:03

調度器Yarn架構

2024-06-06 09:47:56

2023-03-26 23:47:32

Go內存模型

2023-08-10 08:01:36

RDB數據AOF

2017-05-08 11:37:41

Go調度器源碼分析程序
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲国产一| 亚洲国产精品一区在线观看 | 亚洲第一av| 久久69精品久久久久久久电影好 | 国产精品揄拍一区二区 | 日日摸日日爽 | 成人精品一区亚洲午夜久久久 | 亚洲视频第一页 | 宅男噜噜噜66一区二区 | 日韩免费高清视频 | 久久久久久黄 | 中文字幕黄色大片 | 国产精品一区二区福利视频 | 91www在线观看 | 亚洲日日操 | 久久高清精品 | 日韩精品一区二区不卡 | 日本精品一区二区三区在线观看视频 | 成人字幕网zmw| av毛片 | 久日精品 | 一区二区三区四区国产 | 久久精品视频在线观看 | 午夜精品一区二区三区在线视 | 一级片在线视频 | 亚洲综合成人网 | 国产激情视频 | 69视频在线播放 | 性色视频| 日韩视频中文字幕 | 亚洲国产精久久久久久久 | 国产999精品久久久影片官网 | 九色网址 | 亚洲另类春色偷拍在线观看 | 一本综合久久 | 51ⅴ精品国产91久久久久久 | 97超碰中文网 | 日屁视频 | 少妇黄色| 久久成人国产精品 | 欧美成人精品 |