【Golang】?jī)?nèi)存對(duì)齊

歡迎關(guān)注微信公眾號(hào):全棧工廠

1. 先看一個(gè)問(wèn)題

請(qǐng)思考30秒想想以下代碼輸出的內(nèi)容是多少?

package main

import (
    "fmt"
    "unsafe"
)

type S1 struct {
    A byte
    B int64
    C byte
}
type S2 struct {
    A byte
    C byte
    B int64
}
func main() {
    s1 := S1{}
    fmt.Printf("S1.A size: %d\n", unsafe.Sizeof(s1.A))
    fmt.Printf("S1.B size: %d\n", unsafe.Sizeof(s1.B))
    fmt.Printf("S1.C size: %d\n", unsafe.Sizeof(s1.C))
    fmt.Printf("S1   size: %d\n\n", unsafe.Sizeof(s1))

    s2 := S2{}
    fmt.Printf("S2.A size: %d\n", unsafe.Sizeof(s2.A))
    fmt.Printf("S2.B size: %d\n", unsafe.Sizeof(s2.B))
    fmt.Printf("S2.C size: %d\n", unsafe.Sizeof(s2.C))
    fmt.Printf("S2   size: %d\n", unsafe.Sizeof(s2))
}

執(zhí)行后代碼輸出:

S1.A size: 1
S1.B size: 8
S1.C size: 1
S1   size: 24

S2.A size: 1
S2.B size: 8
S2.C size: 1
S2   size: 16

你或許會(huì)疑問(wèn),為什么S1和S2所占存儲(chǔ)空間不僅不是A、B、C總和10而且S1和S2所占空間也各不一樣?問(wèn)題的關(guān)鍵就在于"內(nèi)存對(duì)齊"。

2. 什么是內(nèi)存對(duì)齊?

在計(jì)算機(jī)中,CPU通過(guò)特定的指令從內(nèi)存中讀取數(shù)據(jù),由于CPU訪問(wèn)內(nèi)存已得到數(shù)據(jù)的時(shí)間要比執(zhí)行指令花費(fèi)的時(shí)間多得多,因此在CPU內(nèi)部提供了一些通用寄存器用來(lái)暫存從內(nèi)存中加載到的數(shù)據(jù),CPU一次讀取的數(shù)據(jù)量為一個(gè)字,字的位數(shù)我們稱之為字長(zhǎng),因此字長(zhǎng)的大小直接決定了CPU一次能處理的數(shù)據(jù)量的大?。灰话闱闆r下,字長(zhǎng)越大,CPU性能越高,我們熟知的64位計(jì)算機(jī)就表示CPU一次能處理的數(shù)據(jù)量為64位即8字節(jié)。
因此,所謂內(nèi)存對(duì)齊就是計(jì)算機(jī)將內(nèi)存中的數(shù)據(jù)按照一個(gè)字的長(zhǎng)度(即:CPU數(shù)據(jù)處理單位)進(jìn)行對(duì)齊,保證CPU以高效的方式精確讀取到所需要的數(shù)據(jù)。

3. 為什么要內(nèi)存對(duì)齊?

3.1 提高性能

如果CPU不按照塊(字)去讀取數(shù)據(jù),而是按照字節(jié)去讀取數(shù)據(jù),那么CPU讀取一個(gè)int64值就需要讀取8次,效率很低,所以最終CPU被設(shè)計(jì)一次讀取一個(gè)字長(zhǎng)的數(shù)據(jù),內(nèi)存的基本存儲(chǔ)結(jié)構(gòu)如下:


如果不進(jìn)行內(nèi)存對(duì)齊的話,一個(gè)int64在內(nèi)存中的存儲(chǔ)位置很可能像下面這樣:


image.png

這樣的話,CPU就需要讀取兩次才能完成這個(gè)int64值的讀取操作,而進(jìn)行內(nèi)存對(duì)齊后,保證每個(gè)變量的值都存儲(chǔ)在整數(shù)倍機(jī)器字長(zhǎng)的內(nèi)存地址上,最小化CPU內(nèi)存讀取次數(shù),提高效率。

3.2 避免出錯(cuò)

不是所有的硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)的;某些硬件平臺(tái)只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常,出現(xiàn)錯(cuò)誤。

4. 問(wèn)題解答

了解內(nèi)存對(duì)齊后,我們?cè)倏次恼麻_(kāi)始我們說(shuō)道的那題,在我的64位計(jì)算機(jī)環(huán)境中,S1和S2在內(nèi)存中的大致位置如下圖所示:


所以,最后S1所占的內(nèi)存空間為24字節(jié),S2所占空間為16字節(jié)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是內(nèi)存對(duì)齊 此時(shí)的 打印值為:16,一個(gè)64長(zhǎng)度int占8字節(jié),兩個(gè)就是16。 此時(shí)的 打印值為:16,4+8...
    Stevennnmmm閱讀 700評(píng)論 0 0
  • 一、結(jié)構(gòu)體內(nèi)存對(duì)齊 1.1 結(jié)構(gòu)體內(nèi)存對(duì)齊三大原則 數(shù)據(jù)成員對(duì)?規(guī)則結(jié)構(gòu)體(struct)或聯(lián)合體(union)的...
    HotPotCat閱讀 619評(píng)論 1 3
  • 如何得到一個(gè)對(duì)象所占內(nèi)存大小? 內(nèi)存對(duì)齊: 為何會(huì)有內(nèi)存對(duì)齊?1.并不是所有硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)。...
    郭老漢閱讀 2,178評(píng)論 2 4
  • 先看一個(gè)結(jié)構(gòu)體 對(duì)于這兩個(gè)結(jié)構(gòu)體,都有a、b、c三個(gè)定義完全一樣的字段,只是在定義結(jié)構(gòu)體的時(shí)候字段順序不一樣而已,...
    cfanbo閱讀 218評(píng)論 0 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂(lè)有人憂愁,有人驚喜有人失落,有的覺(jué)得收獲滿滿有...
    陌忘宇閱讀 8,814評(píng)論 28 54

友情鏈接更多精彩內(nèi)容