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)
給型別重新命名之後,型別的大小並沒有發生改變
> 轉載請註明出處 > 本文連結:<http://hatlonely.com/2018/03/17/golang-%E5%AD%97%E8%8A%82%E5%AF%B9%E9%BD%90/>
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- C++ 位元組對齊C++
- c/c++ 位元組對齊C++
- 【C/C++】5.位元組對齊和位元組填充C++
- iOS 記憶體位元組對齊iOS記憶體
- 【C++】C++的位元組對齊C++
- linux 改變GCC編譯器的位元組對齊方式LinuxGC編譯
- 【編譯製導指令】#pragma pack - 位元組數基準對齊編譯
- 1分鐘瞭解C語言正確使用位元組對齊及#pragma pack的方法C語言
- 大廠齊出海:位元組忙種草,網易愛社交
- 位元組豆包、武大提出 CAL:透過視覺相關的 token 增強多模態對齊效果視覺
- 難對齊、難保障、難管理?一文了解位元組跳動如何解決資料SLA治理難題
- 快手遊戲:版圖成形,對標位元組遊戲
- vxe-table 設定單元格對齊方式,左對齊、右對齊
- 位元組碼
- 位元組流
- linux對齊文字Linux
- 對線面試官 | 位元組跳動一面面試
- 位、位元組、字
- 寬位元組注入
- Java 位元組碼Java
- 位元組碼指令
- 位元組開源大模型量化新思路,2-bit量化模型精度齊平fp16大模型
- 對,遊戲公司都是位元組跳動(核心)合作伙伴遊戲
- 位元組跳動1/3員工反對取消“大小周”
- canvas textAlign 文字對齊Canvas
- css居中對齊大全CSS
- 記憶體對齊記憶體
- 【成都】位元大陸招聘Golang工程師Golang工程師
- 什麼是位元組碼?python位元組碼詳細介紹!Python
- 如何讓文字居右對齊,換行後又居左對齊
- 人類自身都對不齊,怎麼對齊AI?新研究全面審視偏好在AI對齊中的作用AI
- modbus和位元組序
- 位元組碼基礎
- 位元組碼詳解
- 位、位元組和字
- 緩衝位元組流#
- 位元組陣列流陣列
- 位元組OpenDay總結