歡迎關(guān)注微信公眾號(hào):全棧工廠
1. 先看一個(gè)問(wèn)題
請(qǐng)思考30秒想想以下代碼輸出的內(nèi)容是多少?
package main
import (
"fmt"
"unsafe"
)
type S1 struct {
A byte
B int64
C byte
}
type S2 struct {
A byte
C byte
B int64
}
func main() {
s1 := S1{}
fmt.Printf("S1.A size: %d\n", unsafe.Sizeof(s1.A))
fmt.Printf("S1.B size: %d\n", unsafe.Sizeof(s1.B))
fmt.Printf("S1.C size: %d\n", unsafe.Sizeof(s1.C))
fmt.Printf("S1 size: %d\n\n", unsafe.Sizeof(s1))
s2 := S2{}
fmt.Printf("S2.A size: %d\n", unsafe.Sizeof(s2.A))
fmt.Printf("S2.B size: %d\n", unsafe.Sizeof(s2.B))
fmt.Printf("S2.C size: %d\n", unsafe.Sizeof(s2.C))
fmt.Printf("S2 size: %d\n", unsafe.Sizeof(s2))
}
執(zhí)行后代碼輸出:
S1.A size: 1
S1.B size: 8
S1.C size: 1
S1 size: 24
S2.A size: 1
S2.B size: 8
S2.C size: 1
S2 size: 16
你或許會(huì)疑問(wèn),為什么S1和S2所占存儲(chǔ)空間不僅不是A、B、C總和10而且S1和S2所占空間也各不一樣?問(wèn)題的關(guān)鍵就在于"內(nèi)存對(duì)齊"。
2. 什么是內(nèi)存對(duì)齊?

在計(jì)算機(jī)中,CPU通過(guò)特定的指令從內(nèi)存中讀取數(shù)據(jù),由于CPU訪問(wèn)內(nèi)存已得到數(shù)據(jù)的時(shí)間要比執(zhí)行指令花費(fèi)的時(shí)間多得多,因此在CPU內(nèi)部提供了一些通用寄存器用來(lái)暫存從內(nèi)存中加載到的數(shù)據(jù),CPU一次讀取的數(shù)據(jù)量為一個(gè)字,字的位數(shù)我們稱之為字長(zhǎng),因此字長(zhǎng)的大小直接決定了CPU一次能處理的數(shù)據(jù)量的大?。灰话闱闆r下,字長(zhǎng)越大,CPU性能越高,我們熟知的64位計(jì)算機(jī)就表示CPU一次能處理的數(shù)據(jù)量為64位即8字節(jié)。
因此,所謂內(nèi)存對(duì)齊就是計(jì)算機(jī)將內(nèi)存中的數(shù)據(jù)按照一個(gè)字的長(zhǎng)度(即:CPU數(shù)據(jù)處理單位)進(jìn)行對(duì)齊,保證CPU以高效的方式精確讀取到所需要的數(shù)據(jù)。
3. 為什么要內(nèi)存對(duì)齊?
3.1 提高性能
如果CPU不按照塊(字)去讀取數(shù)據(jù),而是按照字節(jié)去讀取數(shù)據(jù),那么CPU讀取一個(gè)int64值就需要讀取8次,效率很低,所以最終CPU被設(shè)計(jì)一次讀取一個(gè)字長(zhǎng)的數(shù)據(jù),內(nèi)存的基本存儲(chǔ)結(jié)構(gòu)如下:

如果不進(jìn)行內(nèi)存對(duì)齊的話,一個(gè)int64在內(nèi)存中的存儲(chǔ)位置很可能像下面這樣:

這樣的話,CPU就需要讀取兩次才能完成這個(gè)int64值的讀取操作,而進(jìn)行內(nèi)存對(duì)齊后,保證每個(gè)變量的值都存儲(chǔ)在整數(shù)倍機(jī)器字長(zhǎng)的內(nèi)存地址上,最小化CPU內(nèi)存讀取次數(shù),提高效率。
3.2 避免出錯(cuò)
不是所有的硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)的;某些硬件平臺(tái)只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常,出現(xiàn)錯(cuò)誤。
4. 問(wèn)題解答
了解內(nèi)存對(duì)齊后,我們?cè)倏次恼麻_(kāi)始我們說(shuō)道的那題,在我的64位計(jì)算機(jī)環(huán)境中,S1和S2在內(nèi)存中的大致位置如下圖所示:


所以,最后S1所占的內(nèi)存空間為24字節(jié),S2所占空間為16字節(jié)。