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

Goroutine 數量控制在多少合適,會影響 GC 和調度?

網絡 通信技術
這是本文要進行探討的主體,因此本文的結構會是先探索基礎知識,再一步步揭開,深入理解這個問題。

[[387141]]

本文轉載自微信公眾號「腦子進煎魚了」,作者陳煎魚。轉載本文請聯系腦子進煎魚了公眾號。

大家好,我是煎魚。

前幾天在讀者交流群里看到一位小伙伴,發出了一個致命提問,那就是:“單機的 goroutine 數量控制在多少比較合適?”。

也許你和群內小伙伴第一反應一樣,會答復 “控制多少,我覺得沒有定論”。

緊接著延伸出了更進一步的疑惑:“goroutine 太多了會影響 gc 和調度吧,主要是怎么預算這個數是合理的呢?”

這是本文要進行探討的主體,因此本文的結構會是先探索基礎知識,再一步步揭開,深入理解這個問題。

Goroutine 是什么

Go 語言作為一個新生編程語言,其令人喜愛的特性之一就是 goroutine。Goroutine 是一個由 Go 運行時管理的輕量級線程,一般稱其為 “協程”。

  1. go f(x, y, z) 

操作系統本身是無法明確感知到 Goroutine 的存在的,Goroutine 的操作和切換歸屬于 “用戶態” 中。

Goroutine 由特定的調度模式來控制,以 “多路復用” 的形式運行在操作系統為 Go 程序分配的幾個系統線程上。

同時創建 Goroutine 的開銷很小,初始只需要 2-4k 的棧空間。Goroutine 本身會根據實際使用情況進行自伸縮,非常輕量。

  1. func say(s string) { 
  2.  for i := 0; i < 9999999; i++ { 
  3.   time.Sleep(100 * time.Millisecond) 
  4.   fmt.Println(s) 
  5.  } 
  6.  
  7. func main() { 
  8.  go say("煎魚"
  9.  say("你好"

人稱可以開幾百幾千萬個的協程小霸王,是 Go 語言的得意之作之一。

調度是什么

既然有了用戶態的代表 Goroutine,操作系統又看不到他。必然需要有某個東西去管理他,才能更好的運作起來。

這指的就是 Go 語言中的調度,最常見、面試最愛問的 GMP 模型。因此接下來將會給大家介紹一下 Go 調度的基礎知識和流程。

下述內容摘自煎魚和 p 神寫的《Go 語言編程之旅》中的章節內容。

調度基礎知識

Go scheduler 的主要功能是針對在處理器上運行的 OS 線程分發可運行的 Goroutine,而我們一提到調度器,就離不開三個經常被提到的縮寫,分別是:

  • G:Goroutine,實際上我們每次調用 go func 就是生成了一個 G。
  • P:Processor,處理器,一般 P 的數量就是處理器的核數,可以通過 GOMAXPROCS 進行修改。
  • M:Machine,系統線程。

這三者交互實際來源于 Go 的 M: N 調度模型。也就是 M 必須與 P 進行綁定,然后不斷地在 M 上循環尋找可運行的 G 來執行相應的任務。

調度流程

我們以 GMP 模型的工作流程圖進行簡單分析,官方圖如下:

  1. 當我們執行 go func() 時,實際上就是創建一個全新的 Goroutine,我們稱它為 G。
  2. 新創建的 G 會被放入 P 的本地隊列(Local Queue)或全局隊列(Global Queue)中,準備下一步的動作。需要注意的一點,這里的 P 指的是創建 G 的 P。
  3. 喚醒或創建 M 以便執行 G。
  4. 不斷地進行事件循環
  5. 尋找在可用狀態下的 G 進行執行任務
  6. 清除后,重新進入事件循環

在描述中有提到全局和本地這兩類隊列,其實在功能上來講都是用于存放正在等待運行的 G,但是不同點在于,本地隊列有數量限制,不允許超過 256 個。

并且在新建 G 時,會優先選擇 P 的本地隊列,如果本地隊列滿了,則將 P 的本地隊列的一半的 G 移動到全局隊列。

這可以理解為調度資源的共享和再平衡。

竊取行為

我們可以看到圖上有 steal 行為,這是用來做什么的呢,我們都知道當你創建新的 G 或者 G 變成可運行狀態時,它會被推送加入到當前 P 的本地隊列中。

其實當 P 執行 G 完畢后,它也會 “干活”,它會將其從本地隊列中彈出 G,同時會檢查當前本地隊列是否為空,如果為空會隨機的從其他 P 的本地隊列中嘗試竊取一半可運行的 G 到自己的名下。

官方圖如下:

在這個例子中,P2 在本地隊列中找不到可以運行的 G,它會執行 work-stealing 調度算法,隨機選擇其它的處理器 P1,并從 P1 的本地隊列中竊取了三個 G 到它自己的本地隊列中去。

至此,P1、P2 都擁有了可運行的 G,P1 多余的 G 也不會被浪費,調度資源將會更加平均的在多個處理器中流轉。

有沒有什么限制

在前面的內容中,我們針對 Go 的調度模型和 Goroutine 做了一個基本介紹和分享。

接下來我們回到主題,思考 “goroutine 太多了,會不會有什么影響”。

在了解 GMP 的基礎知識后,我們要知道在協程的運行過程中,真正干活的 GPM 又分別被什么約束?

煎魚帶大家分別從 GMP 來逐步分析。

M 的限制

第一,要知道在協程的執行中,真正干活的是 GPM 中的哪一個?

那勢必是 M(系統線程) 了,因為 G 是用戶態上的東西,最終執行都是得映射,對應到 M 這一個系統線程上去運行。

那么 M 有沒有限制呢?

答案是:有的。在 Go 語言中,M 的默認數量限制是 10000,如果超出則會報錯:

  1. GO: runtime: program exceeds 10000-thread limit 

通常只有在 Goroutine 出現阻塞操作的情況下,才會遇到這種情況。這可能也預示著你的程序有問題。

若確切是需要那么多,還可以通過 debug.SetMaxThreads 方法進行設置。

G 的限制

第二,那 G 呢,Goroutine 的創建數量是否有限制?

答案是:沒有。但理論上會受內存的影響,假設一個 Goroutine 創建需要 4k(via @GoWKH):

  • 4k * 80,000 = 320,000k ≈ 0.3G內存
  • 4k * 1,000,000 = 4,000,000k ≈ 4G內存

以此就可以相對計算出來一臺單機在通俗情況下,所能夠創建 Goroutine 的大概數量級別。

注:Goroutine 創建所需申請的 2-4k 是需要連續的內存塊。

P 的限制

第三,那 P 呢,P 的數量是否有限制,受什么影響?

答案是:有限制。P 的數量受環境變量 GOMAXPROCS 的直接影響。

環境變量 GOMAXPROCS 又是什么?在 Go 語言中,通過設置 GOMAXPROCS,用戶可以調整調度中 P(Processor)的數量。

另一個重點在于,與 P 相關聯的的 M(系統線程),是需要綁定 P 才能進行具體的任務執行的,因此 P 的多少會影響到 Go 程序的運行表現。

P 的數量基本是受本機的核數影響,沒必要太過度糾結他。

那 P 的數量是否會影響 Goroutine 的數量創建呢?

答案是:不影響。且 Goroutine 多了少了,P 也該干嘛干嘛,不會帶來災難性問題。

何為之合理

在介紹完 GMP 各自的限制后,我們回到一個重點,就是 “Goroutine 數量怎么預算,才叫合理?”。

“合理” 這個詞,是需要看具體場景來定義的,可結合上述對 GPM 的學習和了解。得出:

  • M:有限制,默認數量限制是 10000,可調整。
  • G:沒限制,但受內存影響。
  • P:受本機的核數影響,可大可小,不影響 G 的數量創建。

Goroutine 數量在 MG 的可控限額以下,多個把個、幾十個,少幾個其實沒有什么影響,就可以稱其為 “合理”。

真實情況

在真實的應用場景中,沒法如此簡單的定義。如果你 Goroutine:

  • 在頻繁請求 HTTP,MySQL,打開文件等,那假設短時間內有幾十萬個協程在跑,那肯定就不大合理了(可能會導致 too many files open)。
  • 常見的 Goroutine 泄露所導致的 CPU、Memory 上漲等,還是得看你的 Goroutine 里具體在跑什么東西。

還是得看 Goroutine 里面跑的是什么東西。

總結

在這篇文章中,分別介紹了 Goroutine、GMP、調度模型的基本知識,針對如下問題進行了展開:

  • 單機的 goroutine 數量控制在多少比較合適?
  • goroutine 太多了會影響 gc 和調度吧,主要是怎么預算這個數是合理的呢?

單機的 goroutine 數量只要控制在限額以下的,都可以認為是 “合理”。

真實場景得看具體里面跑的是什么,跑的如果是 “資源怪獸”,只運行幾個 Goroutine 都可以跑死。

 

因此想定義 “預算”,就得看跑的什么了。

 

責任編輯:武曉燕 來源: 腦子進煎魚了
相關推薦

2023-11-20 22:55:00

Goroutine調度器

2018-04-19 10:39:45

大數據資源控制大數據平臺

2025-04-02 00:00:03

2025-01-15 09:13:53

2022-02-18 15:07:29

goroutinepanic協程

2009-06-04 14:58:13

2021-06-29 23:40:19

Golang語言并發

2010-02-03 23:04:31

流量控制P2P華夏創新

2023-10-08 12:14:42

Sentinel流量控制

2009-04-08 10:40:03

2015-01-05 17:24:20

JMP

2020-10-16 15:35:13

Go代碼框架

2014-07-24 09:29:30

2010-05-27 11:03:44

Linux流量控制

2021-09-09 09:46:25

Goroutine 函數runtime

2010-05-27 10:43:29

Linux流量控制

2013-07-22 14:25:29

iOS開發ASIHTTPRequ

2011-06-23 09:09:37

流量控制

2022-05-24 12:42:24

物聯網

2010-05-04 15:51:26

負載均衡器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜视频在线观看网址 | 国产精品一区久久久久 | 久久尤物免费一区二区三区 | 亚洲一区二区三区在线播放 | 色婷婷综合久久久中字幕精品久久 | 精品视频免费在线 | 91av在线免费观看 | 午夜激情网 | 欧美日韩国产一区二区三区 | 欧美精品 在线观看 | 国产日韩欧美精品 | 中文字幕在线观看第一页 | 日本欧美在线视频 | 中文字幕亚洲国产 | 久草影视在线 | 91资源在线| 亚洲免费在线播放 | 五月婷婷在线播放 | 久久久精品一区二区 | 美女中文字幕视频 | 午夜影院在线观看 | 国产精品一区二区免费看 | 国产欧美一区二区精品忘忧草 | 91视频久久 | 日韩欧美在线观看 | 久久天天综合 | 亚洲欧美一区二区三区国产精品 | 欧美日韩在线播放 | 国产精品一二三区在线观看 | 福利视频网址 | 国产成人精品久久 | 久久伊人青青草 | 国产精品久久久久久中文字 | 9999在线视频 | 久久草视频 | 亚洲在线一区二区 | 欧美成人精品一区二区三区 | 久久精品视频在线观看 | 久久国产精品-国产精品 | 亚洲精品一 | 成人一区在线观看 |