golang sync.once done 熱路徑
阿新 • • 發佈:2022-04-21
sync.once 為什麼會將done放在結構體第一個欄位,就能夠提升效能了?
我們先來看看sync.once的結構體:
// Once is an object that will perform exactly one action. // // A Once must not be copied after first use. type Once struct { // done indicates whether the action has been performed. // It is first in the struct because it is used in the hot path. // The hot path is inlined at every call site. // Placing done first allows more compact instructions on some architectures (amd64/386), // and fewer instructions (to calculate offset) on other architectures. done uint32 m Mutex }
從欄位 done 前有一段註釋,說明了done 為什麼是第一個欄位。
done 在熱路徑中,done 放在第一個欄位,能夠減少 CPU 指令,也就是說,這樣做能夠提升效能。
熱路徑(hot path)是程式非常頻繁執行的一系列指令,sync.Once 絕大部分場景都會訪問 o.done,在熱路徑上是比較好理解的。如果 hot path 編譯後的機器碼指令更少,更直接,必然是能夠提升效能的。
為什麼放在第一個欄位就能夠減少指令呢?因為結構體第一個欄位的地址和結構體的指標是相同的,如果是第一個欄位,直接對結構體的指標解引用即可。如果是其他的欄位,除了結構體指標外,還需要計算與第一個值的偏移(calculate offset)。在機器碼中,偏移量是隨指令傳遞的附加值,CPU 需要做一次偏移值與指標的加法運算,才能獲取要訪問的值的地址。因為,訪問第一個欄位的機器程式碼更緊湊,速度更快。