1. 程式人生 > 其它 >golang記憶體對齊

golang記憶體對齊

技術標籤:golangmalloc

記憶體對齊

go屬於c語言家族,很多概念與c語言相同。記憶體對齊也可以叫做記憶體地址的對齊。至於為什麼需要記憶體對齊,主要有以下兩個原因:

  1. 高效,cpu每次讀取一個自然字(取決於架構,32位架構上為4位元組,64位架構上為8位元組),如果地址都是對齊的,那麼cpu一個週期就可讀取需要資料,如果存在跨記憶體邊界的情況則需要進行多次讀取拼接操作,則就無形增加了cpu的負擔
  2. 跨平臺,在某些硬體平臺上僅能在特定地址上訪問特定型別,從特定地址開始存取,如果沒有記憶體保證硬體可能會報告錯誤

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