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++
- 記憶體位元組對齊記憶體
- iOS 記憶體位元組對齊iOS記憶體
- 【C++】C++的位元組對齊C++
- <摘錄>位元組對齊與結構體大小結構體
- C/C++ 結構體位元組對齊詳解C++結構體
- 淺談虛擬函式表與位元組對齊函式
- C語言:記憶體位元組對齊詳解C語言記憶體
- C/C++—— 記憶體位元組對齊規則C++記憶體
- 點陣圖四位元組對齊問題
- linux 改變GCC編譯器的位元組對齊方式LinuxGC編譯
- 【編譯製導指令】#pragma pack - 位元組數基準對齊編譯
- c++記憶體中位元組對齊問題詳解C++記憶體
- 1分鐘瞭解C語言正確使用位元組對齊及#pragma pack的方法C語言
- JVM 層對 jar 包位元組碼加密JVMJAR加密
- 快手遊戲:版圖成形,對標位元組遊戲
- 難對齊、難保障、難管理?一文了解位元組跳動如何解決資料SLA治理難題
- 對線面試官 | 位元組跳動一面面試
- Java 位元組碼Java
- 理解位元組序
- 對,遊戲公司都是位元組跳動(核心)合作伙伴遊戲
- 位元組跳動近日申請多個“位元組遊戲”商標遊戲
- .NET刪除位元組陣列中的0位元組陣列
- C# TripleDES NoPadding 時對待加密內容進行補位元組(8個位元組為一個Block)C#padding加密BloC
- 位元組碼基礎
- JS 位元組流 解析JS
- 位元組陣列流陣列
- 位元組碼詳解
- Java位元組碼指令Java
- modbus和位元組序
- 對齊之美
- 文字對齊位置
- 什麼是位元組碼?python位元組碼詳細介紹!Python
- UICollectionView左對齊流水佈局、右對齊流水佈局UIView