【Golang】內(nèi)存對齊

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

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

請思考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ì)疑問,為什么S1和S2所占存儲(chǔ)空間不僅不是A锭汛、B秃臣、C總和10而且S1和S2所占空間也各不一樣?問題的關(guān)鍵就在于"內(nèi)存對齊"淮蜈。

2. 什么是內(nèi)存對齊斋攀?

在計(jì)算機(jī)中,CPU通過特定的指令從內(nèi)存中讀取數(shù)據(jù)梧田,由于CPU訪問內(nèi)存已得到數(shù)據(jù)的時(shí)間要比執(zhí)行指令花費(fèi)的時(shí)間多得多淳蔼,因此在CPU內(nèi)部提供了一些通用寄存器用來暫存從內(nèi)存中加載到的數(shù)據(jù),CPU一次讀取的數(shù)據(jù)量為一個(gè)字裁眯,字的位數(shù)我們稱之為字長鹉梨,因此字長的大小直接決定了CPU一次能處理的數(shù)據(jù)量的大小穿稳;一般情況下存皂,字長越大,CPU性能越高逢艘,我們熟知的64位計(jì)算機(jī)就表示CPU一次能處理的數(shù)據(jù)量為64位即8字節(jié)艰垂。
因此,所謂內(nèi)存對齊就是計(jì)算機(jī)將內(nèi)存中的數(shù)據(jù)按照一個(gè)字的長度(即:CPU數(shù)據(jù)處理單位)進(jìn)行對齊埋虹,保證CPU以高效的方式精確讀取到所需要的數(shù)據(jù)。

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

3.1 提高性能

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


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


image.png

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

3.2 避免出錯(cuò)

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

4. 問題解答

了解內(nèi)存對齊后黔攒,我們再看文章開始我們說道的那題,在我的64位計(jì)算機(jī)環(huán)境中强缘,S1和S2在內(nèi)存中的大致位置如下圖所示:


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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赏胚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子辞友,更是在濱河造成了極大的恐慌栅哀,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件称龙,死亡現(xiàn)場離奇詭異留拾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鲫尊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門痴柔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人疫向,你說我怎么就攤上這事咳蔚。” “怎么了搔驼?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵谈火,是天一觀的道長。 經(jīng)常有香客問我舌涨,道長糯耍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任囊嘉,我火速辦了婚禮温技,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扭粱。我一直安慰自己舵鳞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布琢蛤。 她就那樣靜靜地躺著蜓堕,像睡著了一般抛虏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上俩滥,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天嘉蕾,我揣著相機(jī)與錄音,去河邊找鬼霜旧。 笑死错忱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挂据。 我是一名探鬼主播以清,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼崎逃!你這毒婦竟也來了掷倔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤个绍,失蹤者是張志新(化名)和其女友劉穎勒葱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巴柿,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凛虽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了广恢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凯旋。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖钉迷,靈堂內(nèi)的尸體忽然破棺而出至非,到底是詐尸還是另有隱情,我是刑警寧澤糠聪,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布荒椭,位于F島的核電站,受9級(jí)特大地震影響舰蟆,放射性物質(zhì)發(fā)生泄漏趣惠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一夭苗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隔缀,春花似錦题造、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丢习。三九已至,卻和暖如春淮悼,著一層夾襖步出監(jiān)牢的瞬間咐低,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工袜腥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留见擦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓羹令,卻偏偏與公主長得像鲤屡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子福侈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 什么是內(nèi)存對齊 此時(shí)的 打印值為:16酒来,一個(gè)64長度int占8字節(jié),兩個(gè)就是16肪凛。 此時(shí)的 打印值為:16堰汉,4+8...
    Stevennnmmm閱讀 489評論 0 0
  • 一、結(jié)構(gòu)體內(nèi)存對齊 1.1 結(jié)構(gòu)體內(nèi)存對齊三大原則 數(shù)據(jù)成員對?規(guī)則結(jié)構(gòu)體(struct)或聯(lián)合體(union)的...
    HotPotCat閱讀 461評論 1 3
  • 如何得到一個(gè)對象所占內(nèi)存大形扒健翘鸭? 內(nèi)存對齊: 為何會(huì)有內(nèi)存對齊?1.并不是所有硬件平臺(tái)都能訪問任意地址上的任意數(shù)據(jù)远荠。...
    郭老漢閱讀 1,914評論 2 4
  • 先看一個(gè)結(jié)構(gòu)體 對于這兩個(gè)結(jié)構(gòu)體矮固,都有a、b譬淳、c三個(gè)定義完全一樣的字段档址,只是在定義結(jié)構(gòu)體的時(shí)候字段順序不一樣而已啸臀,...
    cfanbo閱讀 88評論 0 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月瘸洛,有人笑有人哭,有人歡樂有人憂愁辕漂,有人驚喜有人失落浦妄,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,523評論 28 53