自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go1.24 新特性:自旋互斥 lock2 優(yōu)化,性能有一定提高!

開(kāi)發(fā) 前端
通過(guò)上述的分析,原作者發(fā)現(xiàn)當(dāng)前的 lock2 實(shí)現(xiàn)雖然理論上允許線程睡眠,但實(shí)際上導(dǎo)致所有線程都在自旋,自旋的線程至少與(并且可能也導(dǎo)致)更慢的鎖傳遞有關(guān),帶來(lái)了不少的性能損耗。

大家好,我是煎魚(yú)。

除了上次跟大家提到的 map 使用 Swiss Table 來(lái)替換 Hashmap 的原始實(shí)現(xiàn)以外。本次 Go1.24 新版本還帶來(lái)了更多的有效優(yōu)化。

今天這篇文章將繼續(xù)和大家一起學(xué)習(xí)自旋互斥 lock2 優(yōu)化。

背景

提案作者 @Rhys Hiltner 在 2024 年提出了改進(jìn)互斥鎖的性能優(yōu)化訴求:

圖片

其個(gè)人對(duì)于 runtime.mutex 值的部分經(jīng)驗(yàn)是:整個(gè)進(jìn)程會(huì)因?yàn)閷?duì)單個(gè) mutex 的需求使得整個(gè)程序緩慢運(yùn)行。

我不認(rèn)為這一點(diǎn)會(huì)讓人感到意外,盡管速度減慢的程度超出了我的預(yù)期。主要的驚喜在于,程序一旦跌落性能懸崖,就很難再恢復(fù)過(guò)來(lái)。

性能測(cè)試

在基準(zhǔn)測(cè)試 ChanContended 中,作者發(fā)現(xiàn)隨著 GOMAXPROCS 的增加,mutex 的性能明顯下降。

  • Intel i7-13700H (linux/amd64):
  • 當(dāng)允許使用 4 個(gè)線程時(shí),整個(gè)進(jìn)程的吞吐量是單線程時(shí)的一半。
  • 當(dāng)允許使用 8 個(gè)線程時(shí),吞吐量再次減半。
  • 當(dāng)允許使用 12 個(gè)線程時(shí),吞吐量再次減半。
  • 在 GOMAXPROCS=20 時(shí),200 次通道操作平均耗時(shí) 44 微秒,平均每 220 納秒調(diào)用一次 unlock2,每次都有機(jī)會(huì)喚醒一個(gè)睡眠線程。
  • M1 MacBook Air (darwin/arm64):
  • 當(dāng)允許使用 5 個(gè)線程時(shí),吞吐量不到單線程時(shí)的一半。

另一個(gè)角度是考慮進(jìn)程的 CPU 占用時(shí)間。

下面的數(shù)據(jù)顯示,在 1.78 秒的掛鐘時(shí)間內(nèi),進(jìn)程的 20 個(gè)線程在 lock2 調(diào)用中總共有 27.74 秒處于 CPU 上。

如下測(cè)試報(bào)告:

$ go test runtime -test.run='^$' -test.bench=ChanContended -test.cpu=20 -test.count=1 -test.cpuprofile=/tmp/p
goos: linux
goarch: amd64
pkg: runtime
cpu: 13th Gen Intel(R) Core(TM) i7-13700H
BenchmarkChanContended-20        26667      44404 ns/op
PASS
ok   runtime 1.785s

$ go tool pprof -peek runtime.lock2 /tmp/p
File: runtime.test
Type: cpu
Time: Jul 24, 2024 at 8:45pm (UTC)
Duration: 1.78s, Total samples = 31.32s (1759.32%)
Showing nodes accounting for 31.32s, 100% of 31.32s total
----------------------------------------------------------+-------------
      flat  flat%   sum%        cum   cum%   calls calls% + context
----------------------------------------------------------+-------------
                                            27.74s   100% |   runtime.lockWithRank
     4.57s 14.59% 14.59%     27.74s 88.57%                | runtime.lock2
                                            19.50s 70.30% |   runtime.procyield
                                             2.74s  9.88% |   runtime.futexsleep
                                             0.84s  3.03% |   runtime.osyield
                                             0.07s  0.25% |   runtime.(*lockTimer).begin
                                             0.02s 0.072% |   runtime.(*lockTimer).end
----------------------------------------------------------+-------------

關(guān)鍵問(wèn)題之一:這些 lock2 相關(guān)的線程并沒(méi)有休眠,而是一直在自旋!

新提案:增加 spinning 狀態(tài)

發(fā)現(xiàn)問(wèn)題

通過(guò)上述的分析,原作者發(fā)現(xiàn)當(dāng)前的 lock2 實(shí)現(xiàn)雖然理論上允許線程睡眠,但實(shí)際上導(dǎo)致所有線程都在自旋,自旋的線程至少與(并且可能也導(dǎo)致)更慢的鎖傳遞有關(guān),帶來(lái)了不少的性能損耗。

@Rhys Hiltner 進(jìn)而提出了新的設(shè)計(jì)方案《Proposal: Improve scalability of runtime.lock2[1]》。大家有興趣的可以認(rèn)真看下。下面提及主要優(yōu)化部分。

圖片

核心優(yōu)化點(diǎn)

核心的觀點(diǎn)在于:擴(kuò)展互斥鎖的 mutex 狀態(tài)字,加入一個(gè)新的標(biāo)志位,稱(chēng)為 “spinning”(旋轉(zhuǎn))。

使用這個(gè) “spinning” 位來(lái)表示是否有一個(gè)等待的線程處于 “醒著并循環(huán)嘗試獲取鎖” 的狀態(tài)。線程之間會(huì)互相排除進(jìn)入 “spinning” 狀態(tài),但它們不會(huì)因?yàn)閲L試獲取這個(gè)標(biāo)志位而阻塞。

只有持有 “spinning” 位的線程可以循環(huán)重新加載 mutex 狀態(tài)字。這個(gè)線程在進(jìn)入休眠之前會(huì)釋放 “spinning” 位。其他等待線程則會(huì)直接進(jìn)入休眠,而不會(huì)嘗試爭(zhēng)奪 “spinning” 位。

當(dāng)某個(gè)線程解鎖互斥鎖時(shí),如果發(fā)現(xiàn)已經(jīng)有線程處于 “醒著并旋轉(zhuǎn)” 的狀態(tài),就可以避免喚醒其他線程。在 Go 運(yùn)行時(shí)的背景下,這種設(shè)計(jì)被稱(chēng)為 “spinbit”(旋轉(zhuǎn)位)。

簡(jiǎn)單來(lái)說(shuō),這個(gè)設(shè)計(jì)的核心目的是:通過(guò)讓一個(gè)線程負(fù)責(zé) “旋轉(zhuǎn)嘗試獲取鎖”,避免所有線程都同時(shí)競(jìng)爭(zhēng)資源,從而減少爭(zhēng)用和不必要的線程切換。

兼容性和多平臺(tái)

本次對(duì)于兼容性有保障,導(dǎo)出 API 沒(méi)有變化。所以我們只需要升級(jí)到新版本 Go1.24 就可以白嫖這個(gè)優(yōu)化點(diǎn)了!

目前該優(yōu)化支持 futex 和 Xchg8 系統(tǒng)調(diào)用兩個(gè)類(lèi)型。futex 專(zhuān)門(mén)用于 GOOS=linux 平臺(tái)。futex 是主要實(shí)現(xiàn),整體綜合表現(xiàn)會(huì)好一些。

在已支持的平臺(tái)上會(huì)默認(rèn)打開(kāi) GOEXPERIMENT=spinbitmutex 以此應(yīng)用該實(shí)驗(yàn)性規(guī)則。如果大家不需要可以進(jìn)行關(guān)閉。

參考資料

[1]Proposal: Improve scalability of runtime.lock2: https://github.com/golang/proposal/blob/master/design/68578-mutex-spinbit.md

責(zé)任編輯:武曉燕 來(lái)源: 腦子進(jìn)煎魚(yú)了
相關(guān)推薦

2025-01-06 09:18:04

2025-02-12 08:50:22

2024-12-30 11:05:28

泛型Go類(lèi)型別名

2024-12-23 08:44:49

2025-02-07 09:18:05

機(jī)制Go函數(shù)

2022-05-05 11:20:08

KubernetesDocker云計(jì)算

2024-09-03 08:49:01

2025-03-07 09:12:28

2025-02-08 11:00:33

2013-05-15 09:37:00

GoGo1.1性能測(cè)試

2022-12-09 08:52:51

Go匿名接口

2022-05-02 09:21:25

微信微信支付

2021-01-14 10:38:41

Java枚舉工具

2021-09-01 07:21:46

堆棧Gopanic

2022-09-30 14:00:50

JavaScrip新特性代碼

2021-09-05 18:25:30

Go命令倉(cāng)庫(kù)

2021-02-02 09:10:12

Go語(yǔ)言二進(jìn)制

2021-09-10 17:26:14

Windows 11Windows微軟

2024-08-07 09:59:56

2021-04-07 20:01:23

Go變量常量
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)