首頁  >  文章  >  後端開發  >  位元組對齊在golang中的使用詳解

位元組對齊在golang中的使用詳解

藏色散人
藏色散人轉載
2021-09-10 16:42:152319瀏覽

本文由go語言教學專欄為大家介紹golang 位元組對齊,希望對需要的朋友有幫助!

最近在做一些效能優化的工作,其中有個結構體佔用的空間比較大,而且在記憶體中的數量又特別多,就在想有沒有優化的空間,想起了c 語言裡面的字節對齊,通過簡單地調整一下字段的順序,就能省出不少內存,這個思路在golang 裡面同樣適用

基本資料大小

在這之前先來看下golang 裡面基本的型別所佔資料的大小

So(unsafe.Sizeof(true), ShouldEqual, 1)
So(unsafe.Sizeof(int8(0)), ShouldEqual, 1)
So(unsafe.Sizeof(int16(0)), ShouldEqual, 2)
So(unsafe.Sizeof(int32(0)), ShouldEqual, 4)
So(unsafe.Sizeof(int64(0)), ShouldEqual, 8)
So(unsafe.Sizeof(int(0)), ShouldEqual, 8)
So(unsafe.Sizeof(float32(0)), ShouldEqual, 4)
So(unsafe.Sizeof(float64(0)), ShouldEqual, 8)
So(unsafe.Sizeof(""), ShouldEqual, 16)
So(unsafe.Sizeof("hello world"), ShouldEqual, 16)
So(unsafe.Sizeof([]int{}), ShouldEqual, 24)
So(unsafe.Sizeof([]int{1, 2, 3}), ShouldEqual, 24)
So(unsafe.Sizeof([3]int{1, 2, 3}), ShouldEqual, 24)
So(unsafe.Sizeof(map[string]string{}), ShouldEqual, 8)
So(unsafe.Sizeof(map[string]string{"1": "one", "2": "two"}), ShouldEqual, 8)
So(unsafe.Sizeof(struct{}{}), ShouldEqual, 0)
  • bool 類型雖然只有一位,但也需要佔用1個位元組,因為電腦是以位元組為單位
  • 64為的機器,一個int 佔8個位元組
  • string 類型佔16個位元組,內部包含一個指向資料的指標(8個位元組)和一個int 的長度(8個位元組)
  • slice 類型佔24個位元組,內部包含一個指向資料的指標(8個位元組)和一個int 的長度(8個位元組)和一個int 的容量(8個位元組)
  • map 類型佔8個位元組,是一個指向map 結構的指標
  • 可以用struct{} 表示空型,這個型別不佔用任何空間,用這個當map 的value,可以講map 當做set 來用

字節對齊

結構體中的各個字段在內存中並不是緊湊排列的,而是按照字節對齊的,比如int 佔8個字節,那麼就只能寫在地址為8的倍數的地址處,至於為什麼要字節對齊,主要是為了效率考慮,而更深層的原理看了一下網上的說法,感覺不是很可靠,就不瞎說了,感興趣可以自己研究下

// |x---|
So(unsafe.Sizeof(struct {
    i8 int8
}{}), ShouldEqual, 1)

簡單封裝一個int8 的結構體,和int8 一樣,只佔1個字節,沒有額外空間

// |x---|xxxx|xx--|
So(unsafe.Sizeof(struct {
    i8  int8
    i32 int32
    i16 int16
}{}), ShouldEqual, 12)

// |x-xx|xxxx|
So(unsafe.Sizeof(struct {
    i8  int8
    i16 int16
    i32 int32
}{}), ShouldEqual, 8)

這兩個結構體裡面的內容完全一樣,調整了一下字段順序,節省了33% 的空間

// |x---|xxxx|xx--|----|xxxx|xxxx|
So(unsafe.Sizeof(struct {
    i8  int8
    i32 int32
    i16 int16
    i64 int64
}{}), ShouldEqual, 24)

// |x-xx|xxxx|xxxx|xxxx|
So(unsafe.Sizeof(struct {
    i8  int8
    i16 int16
    i32 int32
    i64 int64
}{}), ShouldEqual, 16)

這裡要注意的是int64 只能出現在8的倍數的位址處,因此第一個結構體中,有連續的4個位元組是空的

type I8 int8
type I16 int16
type I32 int32

So(unsafe.Sizeof(struct {
    i8  I8
    i16 I16
    i32 I32
}{}), ShouldEqual, 8)

給型別重新命名之後,型別的大小並沒有改變

更多golang相關知識,請造訪golang教學欄位!

以上是位元組對齊在golang中的使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除