golang記憶體對齊
阿新 • • 發佈:2020-12-15
記憶體對齊
go屬於c語言家族,很多概念與c語言相同。記憶體對齊也可以叫做記憶體地址的對齊。至於為什麼需要記憶體對齊,主要有以下兩個原因:
- 高效,cpu每次讀取一個自然字(取決於架構,32位架構上為4位元組,64位架構上為8位元組),如果地址都是對齊的,那麼cpu一個週期就可讀取需要資料,如果存在跨記憶體邊界的情況則需要進行多次讀取拼接操作,則就無形增加了cpu的負擔
- 跨平臺,在某些硬體平臺上僅能在特定地址上訪問特定型別,從特定地址開始存取,如果沒有記憶體保證硬體可能會報告錯誤
go中的記憶體對齊保證
golang對齊保證分為型別對齊保證和型別欄位對齊保證
unsafe.Alignof(x)
和unsafe.Alignof(x.t)
進行獲取,上述方法在編譯時估值。如果需要在執行時獲取可以使用reflect.TypeOf(x).Align()
和reflect.TypeOf(x).FeildAlign()
方法進行獲取對齊保證也可以簡單的看作每個值都是從對齊的地址開始存放的(特定地址)
a:=1
fmt.Println(unsafe.Alignof(a))// 8
fmt.Println(reflect.TypeOf(a).Align())// 8
var b struct{
A int
}
b.A = 1
fmt.Println(unsafe. Alignof(b.A))// 8
fmt.Println(reflect.TypeOf(b).FieldAlign())// 8
需要注意的是對齊保證的大小不是型別的大小(unsafe.Sizeof()
獲取),比如int64大小為8個位元組,在32位上的對齊保證位4個位元組,在64位上的對齊保證為8個位元組
結構體型別的對齊保證
結構體型別對齊保證取決於欄位的最大對齊保證,尺寸需為欄位最大對齊保證的整數倍。
type S struct{
A int8
// 為了讓B為4位元組對齊,那麼需要在這裡填充3個位元組
B int32
C int8
// 為了保證S對齊為4位元組倍數,那麼需要在這填充3個位元組
}
上述結構體的變數的對齊保證與int32型別對齊保證相同為4個位元組的整數倍。所以最終記憶體大小為(1+3+4+1+3)=12位元組。
切片型別的對齊保證
眾所周知,切片型別的底層型別為一個結構體
type slice struct {
array unsafe.Pointer
len int
cap int
}
返回也是就是該結構體,可以使用unsafe.Sizeof()
方法檢視,可知記憶體大小始終為24(64位架構),即一個指標8,加一個長度8、一個容量8.切片不同於map、chan返回的是指向底層結構體的指標。根據結構體的記憶體對齊保證可得,切片的記憶體對齊保證為8,固切片的記憶體大小必須為8n