圖解 Go GOMAXPROCS 和實時更新

?? 這篇文章基于 Go 1.13。
GOMAXPROCS 控制著同時執(zhí)行代碼的 OS 線程的最大數(shù)量。這(GOMAXPROCS 值的設(shè)定)在程序啟動期間,甚至在程序運行期間完成。一般來說,Go 將這個值設(shè)置為可用邏輯 CPU 的數(shù)量,但并不總是這樣。
默認(rèn)值
從 Go 1.5[1] 開始,GOMAXPROCS 的默認(rèn)值由 1 改成了可見 CPU 的數(shù)量。這個改動也許是由于 Go 調(diào)度器和 Goroutine 上下文切換的改善。確實,在 Go 的早期階段,旨在以頻繁切換 Goroutine 的方式來并行工作的程序遭受了進(jìn)程切換的困擾。
這個 GOMAXPROCS 新值的提案[2]提供了展示這個提升的基準(zhǔn)測試結(jié)果:
第一個基準(zhǔn)測試,創(chuàng)建了 100 個由 channel 通信的 goroutine, 這些 channel 包括緩存的和非緩存的:

GOMAXPROCS 值帶來的調(diào)度器性能提升用于質(zhì)數(shù)生成的第二個基準(zhǔn)測試展示了使用更多的核心將一個性能急劇下降的趨勢轉(zhuǎn)變?yōu)榱艘粋€巨大提升的趨勢:

GOMAXPROCS 值現(xiàn)在產(chǎn)生了很大的積極影響調(diào)度器已明顯解決了單線程程序中遇到的問題,且現(xiàn)在可以很好的擴(kuò)展。
在運行期間更新
Go 允許 GOMAXPROCS 在程序執(zhí)行期間的任何時候進(jìn)行更新。更新可以是虛擬機(jī)或者容器重新配置可用 CPU 數(shù)量所造成的。由于增減處理器數(shù)量的指令可以在任何時候發(fā)生,因此 Go 一進(jìn)入“停止世界(Stop the World)”階段該指令就生效。增加新的處理器是十分簡單直接的,創(chuàng)建本地緩存 mcache 并且將新添加的處理器放入空閑隊列中。這是當(dāng)處理器從兩個變成增長為三個時,一個新分配的 P 的例子:

GOMAXPROCS 增加一個處理器之后,當(dāng)重新開始調(diào)度的時候,新的 P 獲取一個 Goroutine 運行:

減少處理器數(shù)量稍微有點復(fù)雜。移除一個 P 需要通過將 Goroutine 轉(zhuǎn)移到全局隊列的方式,將其本地的 Goroutine 隊列清空:

之后,要移除的 P 必須釋放本地的 mcache 以便重復(fù)使用:

這是當(dāng) P 從二調(diào)整到一,之后再從一調(diào)整到三個 P 的追蹤信息的例子:

GOMAXPROCS=1
調(diào)整 GOMAXPROCS 到一個更大的值并不意味著你的程序一定會運行的更快。Go 文檔解釋地很清楚:
這取決于程序的性質(zhì)。本質(zhì)上是順序處理的問題無法通過增加 Goroutine 的方式提高處理速度。當(dāng)問題本質(zhì)上是并行處理的時候,并發(fā)才會變成并行。
來看下對于某些程序而言,并發(fā)是如何滿足需要的。這是一些檢查某些 URL 的代碼,用來感知這些網(wǎng)站是否正常運行:

由于代碼執(zhí)行過程中有很多停頓,這段示例代碼在并發(fā)情況下工作地很好,給了 Go 調(diào)度器空間在等待期間運行其他 goroutine。這是通過 test 包的 -cpu=1,2,4,5 標(biāo)志,拿到的不同 GOMAXPROCS 的值的情況下的基準(zhǔn)測試結(jié)果:
name?????????time/op
URLsCheck-8??4.19s?±?2%
URLsCheck-4??4.30s?±?5%
URLsCheck-2??4.33s?±?4%
URLsCheck-1??4.14s?±?1%
在這里增加并行不會帶來任何的性能提升。使用 CPU 的全部容量在許多時候會帶來性能提升。然而,最好在不同的(GOMAXPROCS)值下運行測試或基準(zhǔn)測試來確定具體的表現(xiàn)。
via: https://medium.com/a-journey-with-go/go-gomaxprocs-live-updates-407ad08624e1
作者:Vincent Blanchon[3]譯者:dust347[4]校對:polaris1119[5]
本文由 GCTT[6] 原創(chuàng)編譯,Go 中文網(wǎng)[7] 榮譽推出
參考資料
Go 1.5: https://golang.org/doc/go1.5
[2]提案: https://docs.google.com/document/d/1At2Ls5_fhJQ59kDK2DFVhFu3g5mATSXqqV5QrxinasI/edit
[3]Vincent Blanchon: https://medium.com/@blanchon.vincent
[4]dust347: https://github.com/dust347
[5]polaris1119: https://github.com/polaris1119
[6]GCTT: https://raw.githubusercontent.com/studygolang/GCTT
[7]Go 中文網(wǎng): https://studygolang.com/
推薦閱讀
