Golang內存對齊

如何得到一個對象所占內存大小?

fmt.Println(unsafe.Sizeof(int64(0))) // "8"

type SizeOfA struct {
    A int
}
unsafe.Sizeof(SizeOfA{0}) // 8

type SizeOfC struct {
    A byte  // 1字節
    C int32 // 4字節
}
unsafe.Sizeof(SizeOfC{0, 0})    // 8
unsafe.Alignof(SizeOfC{0, 0}) // 4
結構體中A byte占1字節,C int32占4字節. SizeOfC占8字節

內存對齊:

為何會有內存對齊?1.并不是所有硬件平臺都能訪問任意地址上的任意數據。2.性能原因 訪問未對齊的內存,處理器需要做兩次內存訪問,而對齊的內存只需訪問一次。
上面代碼SizeOfC中元素一共5個字節,而實際結構體占8字節
是因為這個結構體的對齊倍數Alignof(SizeOfC) = 4.也就是說,結構體占的實際大小必須是4的倍數,也就是8字節。

type SizeOfD struct {
    A byte
    B [5]int32
}
unsafe.Sizeof(SizeOfD{})   // 24
unsafe.Alignof(SizeOfD{})  // 4

Alignof返回的對齊數是結構體中最大元素所占的內存數,不超過8,如果元素是數組那么取數組類型所占的內存值而不是整個數組的值

type SizeOfE struct {
    A byte  // 1
    B int64 // 8
    C byte  // 1
}
unsafe.Sizeof(SizeOfE{})    // 24
unsafe.Alignof(SizeOfE{}) // 8

SizeOfE中,元素的大小分別為1,8,1,但是實際結構體占24字節,遠超元素實際大小,因為內存對齊原因,最開始分配的8字節中包含了1字節的A,剩余的7字節不足以放下B,又為B分配了8字節,剩余的C獨占再分配的8字節。

type SizeOfE struct {
    A byte  // 1
    C byte  // 1
    B int64 // 8    
}
unsafe.Sizeof(SizeOfE{})    // 16
unsafe.Alignof(SizeOfE{}) // 8

換一種寫法,把A,C放到上面,B放到下面。這時SizeOfE占用的內存變為了16字節。因為首先分配的8字節足以放下A和C,省去了8字節的空間。
上面一個結構體中元素的不同順序足以導致內存分配的巨大差異。前一種寫法產生了很多的內存空洞,導致結構體不夠緊湊,造成內存浪費。

下面我們來看一下結構體中元素的內存布局:

unsafe.Offsetof:返回結構體中元素所在內存的偏移量

type SizeOfF struct {
    A byte
    C int16
    B int64
    D int32
}
unsafe.Offsetof(SizeOfF{}.A) // 0
unsafe.Offsetof(SizeOfF{}.C) // 2
unsafe.Offsetof(SizeOfF{}.B) // 8
unsafe.Offsetof(SizeOfF{}.D) // 16

下圖為內存分布圖:


SizeOfF 內存布局圖

藍色區域是元素實際所占內存,灰色為內存空洞。

下面總結一下go語言中各種類型所占內存大小(x64環境下):

X64下1機器字節=8字節


Golang內置類型占用內存大小

總結一下:

從例子中可以看出,結構體中元素不同順序的排列會導致內存分配的極大差異,不好的順序會產生許多的內存空洞,造成大量內存浪費。
雖然這幾個函數都在unsafe包中,但是他們并不是不安全的。在需要優化內存空間時這幾個函數非常有用。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容

  • unsafe 包簡單說明 unsafe,顧名思義,是不安全的,Go定義這個包名也是這個意思,讓我們盡可能的不要使用...
    Gopherzhang閱讀 1,532評論 8 3
  • Swift1> Swift和OC的區別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,125評論 1 32
  • 前言 Redis是目前最火爆的內存數據庫之一,通過在內存中讀寫數據,大大提高了讀寫速度,可以說Redis是實現網站...
    小陳阿飛閱讀 811評論 0 1
  • 感恩感謝被照顧。今天再次被我家榮榮的廚藝征服,自制全素麻辣香鍋,太棒了!還有佳佳大盆友蒸的米飯。 感恩感謝旁觀。今...
    enhui1994閱讀 159評論 0 1
  • 近來總是做夢,一做一個晚上。醒來什么都忘了,有時能記住一點,有時一點也記不住了。 夢終究是夢,它是見不了陽光的。夢...
    滴水穿石910閱讀 163評論 0 1