溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

字節(jié)對齊在golang中使用的示例分析

發(fā)布時(shí)間:2021-09-10 17:07:27 來源:億速云 閱讀:117 作者:柒染 欄目:編程語言

本篇文章為大家展示了字節(jié)對齊在golang中使用的示例分析,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

最近在做一些性能優(yōu)化的工作,其中有個(gè)結(jié)構(gòu)體占用的空間比較大,而且在內(nèi)存中的數(shù)量又特別多,就在想有沒有優(yōu)化的空間,想起了 c 語言里面的字節(jié)對齊,通過簡單地調(diào)整一下字段的順序,就能省出不少內(nèi)存,這個(gè)思路在 golang 里面同樣適用

基本數(shù)據(jù)大小

在這之前先來看下 golang 里面基本的類型所占數(shù)據(jù)的大小

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個(gè)字節(jié),因?yàn)橛?jì)算機(jī)是以字節(jié)為單位

  • 64為的機(jī)器,一個(gè) int 占8個(gè)字節(jié)

  • string 類型占16個(gè)字節(jié),內(nèi)部包含一個(gè)指向數(shù)據(jù)的指針(8個(gè)字節(jié))和一個(gè) int 的長度(8個(gè)字節(jié))

  • slice 類型占24個(gè)字節(jié),內(nèi)部包含一個(gè)指向數(shù)據(jù)的指針(8個(gè)字節(jié))和一個(gè) int 的長度(8個(gè)字節(jié))和一個(gè) int 的容量(8個(gè)字節(jié))

  • map 類型占8個(gè)字節(jié),是一個(gè)指向 map 結(jié)構(gòu)的指針

  • 可以用 struct{} 表示空類型,這個(gè)類型不占用任何空間,用這個(gè)作為 map 的 value,可以講 map 當(dāng)做 set 來用

字節(jié)對齊

結(jié)構(gòu)體中的各個(gè)字段在內(nèi)存中并不是緊湊排列的,而是按照字節(jié)對齊的,比如 int 占8個(gè)字節(jié),那么就只能寫在地址為8的倍數(shù)的地址處,至于為什么要字節(jié)對齊,主要是為了效率考慮,而更深層的原理看了一下網(wǎng)上的說法,感覺不是很靠譜,就不瞎說了,感興趣可以自己研究下

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

簡單封裝一個(gè) int8 的結(jié)構(gòu)體,和 int8 一樣,僅占1個(gè)字節(jié),沒有額外空間

// |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)

這兩個(gè)結(jié)構(gòu)體里面的內(nèi)容完全一樣,調(diào)整了一下字段順序,節(jié)省了 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 只能出現(xiàn)在8的倍數(shù)的地址處,因此第一個(gè)結(jié)構(gòu)體中,有連續(xù)的4個(gè)字節(jié)是空的

type I8 int8
type I16 int16
type I32 int32

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

給類型重命名之后,類型的大小并沒有發(fā)生改變

上述內(nèi)容就是字節(jié)對齊在golang中使用的示例分析,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI