Go的Sizeof和內(nèi)存對(duì)齊淺析

類型和Sizeof

Go的類型系統(tǒng)比較簡(jiǎn)單枫慷,從reflect包可以窺得一二:

// A Kind represents the specific kind of type that a Type represents.
// The zero Kind is not a valid kind.
type Kind uint

const (
    Invalid Kind = iota
    Bool
    Int
    Int8
    Int16
    Int32
    Int64
    Uint
    Uint8
    Uint16
    Uint32
    Uint64
    Uintptr
    Float32
    Float64
    Complex64
    Complex128
    Array
    Chan
    Func
    Interface
    Map
    Ptr
    Slice
    String
    Struct
    UnsafePointer
)

針對(duì)每一種類型,了解每種類型所占的空間對(duì)于編寫以及優(yōu)化Go程序有較大的幫助浪规。以下測(cè)試均在GOARCH=amd64環(huán)境下

type Sizeof(字節(jié)數(shù))
Bool 1
Int 8
Uint 8
Uintptr 8
Array Sizeof(type) * len
Chan 8
Func 8
Interface 16
Map 8
Ptr(Go指針) 8
Slice 8
String 16
Struct 需考慮字節(jié)對(duì)齊和填充
UnsafePointer 8

Alignment and padding

Go是一個(gè)C家族語(yǔ)言或听,Go的結(jié)構(gòu)體類型基于C語(yǔ)言的結(jié)構(gòu)體演化而來,因此關(guān)于字節(jié)對(duì)齊等概念也是通用的笋婿。通過調(diào)整結(jié)構(gòu)體字段的聲明順序有時(shí)可以優(yōu)化程序性能誉裆,減少內(nèi)存消耗,在一些內(nèi)存受限的嵌入式系統(tǒng)或者操作系統(tǒng)內(nèi)核缸濒,或者你的程序達(dá)到了內(nèi)存上限的場(chǎng)景足丢,只要內(nèi)存是有限的,該項(xiàng)技術(shù)就仍然有用庇配。

關(guān)于內(nèi)存對(duì)齊斩跌,在Go語(yǔ)言規(guī)范中可以找到如下描述:

Computer architectures may require memory addresses to be aligned; that is, for addresses of a variable to be a multiple of a factor, the variable's type's alignment. The function Alignof takes an expression denoting a variable of any type and returns the alignment of the (type of the) variable in bytes. For a variable x:
uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0

關(guān)于更詳盡的Go內(nèi)存布局可參考Go語(yǔ)言規(guī)范go101 Memory Layouts

關(guān)于以C語(yǔ)言結(jié)構(gòu)體為基礎(chǔ)的字節(jié)對(duì)齊和填充可參考這篇介紹詳盡的文章:

關(guān)于結(jié)構(gòu)體字段的字節(jié)偏移和大小可以使用下面的工具進(jìn)行顯示和字段調(diào)整參考:

另外捞慌,這是一個(gè)優(yōu)化的小例子:

從Go1.5開始耀鸦,有一點(diǎn)需要注意。在一個(gè)結(jié)構(gòu)體結(jié)尾的一個(gè)零長(zhǎng)度的字段(一個(gè)零長(zhǎng)度的數(shù)組或者空結(jié)構(gòu)體)要占一個(gè)字節(jié)啸澡。在padding-is-hard這篇文章可以找到詳細(xì)的討論袖订。下面是一個(gè)簡(jiǎn)單的測(cè)試:

type EmptyEndStruct struct {
        Field bool
        _      struct{}
}
testT := EmptyEndStruct{true, struct{}{}}
fmt.Println("struct type Sizeof:", unsafe.Sizeof(testT)) // struct type Sizeof: 2

unsafe、reflect和sync/atomic

unsafe包在編譯時(shí)進(jìn)行計(jì)算嗅虏,而reflect在運(yùn)行時(shí)計(jì)算對(duì)齊的長(zhǎng)度

  • unsafe.Alignof(t)
  • unsafe.Alignof(x.t)
  • reflect.TypeOf(t).Align()
  • reflect.TypeOf(t).FieldAlign()

另外洛姑,在sync/atomic的文檔底部,詳細(xì)說明了atomic包的64位原子函數(shù)由于字節(jié)對(duì)齊導(dǎo)致的在32位芯片上的使用限制皮服。

Sizeof完整的測(cè)試代碼

    boolTemp := true
    intTemp := 99
    var uintTemp uint = 99
    uintptrTemp := (uintptr)(unsafe.Pointer(&intTemp))
    arrayTemp := [3]int8{1, 2}
    // arrayTemp2 := [3]string{}
    chanTemp := make(<-chan string, 100)
    ll := func(a int, b string) (int, error) {
        return a + 1, errors.New("a error")
    }
    type interfaceTest interface {
        test(int, int) int
    }
    var interfaceTemp interfaceTest
    mapTemp := make(map[string]string)
    sliceTemp := []int{1, 2, 3}
    stringTemp := "hongyi"
    // Alignment and padding
    type StructTemp struct {
        Field3 bool   // 1
        Field2 int    //8
        Field4 uint64 // 8
        Field1 string //16
    }
    structTemp1 := StructTemp{true, 1, 89, "hongyi"}
    unsafePointerTemp := unsafe.Pointer(&intTemp)

    fmt.Println("bool type Sizeof:", unsafe.Sizeof(boolTemp))
    fmt.Println("int type Sizeof:", unsafe.Sizeof(intTemp))
    fmt.Println("uint type Sizeof:", unsafe.Sizeof(uintTemp))
    fmt.Println("uintptr type Sizeof:", unsafe.Sizeof(uintptrTemp))
    fmt.Println("array type Sizeof:", unsafe.Sizeof(arrayTemp))
    fmt.Println("chan type Sizeof:", unsafe.Sizeof(chanTemp))
    fmt.Println("func type Sizeof:", unsafe.Sizeof(ll))
    fmt.Println("interface type Sizeof:", unsafe.Sizeof(interfaceTemp))
    fmt.Println("map type Sizeof:", unsafe.Sizeof(mapTemp))
    if reflect.TypeOf(&intTemp).Kind() == reflect.Ptr {
        fmt.Println("ptr type Sizeof:", unsafe.Sizeof(&intTemp))
    }
    fmt.Println("slice type Sizeof:", unsafe.Sizeof(&sliceTemp))
    fmt.Println("string type Sizeof:", unsafe.Sizeof(stringTemp))
    fmt.Println("struct type Sizeof:", unsafe.Sizeof(structTemp1))
    fmt.Println("unsafePointer type Sizeof:", unsafe.Sizeof(unsafePointerTemp))

Go結(jié)構(gòu)體內(nèi)存對(duì)齊舉例

type T1 struct {
    a int8

    // On 64-bit architectures, to make field b
    // 8-byte aligned, 7 bytes need to be padded
    // here. On 32-bit architectures, to make
    // field b 4-byte aligned, 3 bytes need to be
    // padded here.

    b int64
    c int16

    // To make the size of type T1 be a multiple
    // of the alignment guarantee of T1, on 64-bit
    // architectures, 6 bytes need to be padded
    // here, and on 32-bit architectures, 2 bytes
    // need to be padded here.
}
// The size of T1 is 24 (= 1 + 7 + 8 + 2 + 6)
// bytes on 64-bit architectures and is 16
// (= 1 + 3 + 8 + 2 + 2) on 32-bit architectures.

type T2 struct {
    a int8

    // To make field c 2-byte aligned, one byte
    // needs to be padded here on both 64-bit
    // and 32-bit architectures.

    c int16

    // On 64-bit architectures, to make field b
    // 8-byte aligned, 4 bytes need to be padded
    // here. On 32-bit architectures, field b is
    // already 4-byte aligned, so no bytes need
    // to be padded here.

    b int64
}
// The size of T2 is 16 (= 1 + 1 + 2 + 4 + 8)
// bytes on 64-bit architectures, and is 12
// (= 1 + 1 + 2 + 8) on 32-bit architectures.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末楞艾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子冰更,更是在濱河造成了極大的恐慌产徊,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜀细,死亡現(xiàn)場(chǎng)離奇詭異舟铜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)奠衔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門谆刨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來塘娶,“玉大人,你說我怎么就攤上這事痊夭〉蟀叮” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵她我,是天一觀的道長(zhǎng)虹曙。 經(jīng)常有香客問我,道長(zhǎng)番舆,這世上最難降的妖魔是什么酝碳? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮恨狈,結(jié)果婚禮上疏哗,老公的妹妹穿的比我還像新娘。我一直安慰自己禾怠,他們只是感情好返奉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吗氏,像睡著了一般芽偏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上弦讽,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天哮针,我揣著相機(jī)與錄音,去河邊找鬼坦袍。 笑死十厢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捂齐。 我是一名探鬼主播蛮放,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼奠宜!你這毒婦竟也來了包颁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤压真,失蹤者是張志新(化名)和其女友劉穎娩嚼,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滴肿,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡岳悟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贵少。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡呵俏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出滔灶,到底是詐尸還是另有隱情普碎,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布录平,位于F島的核電站麻车,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏斗这。R本人自食惡果不足惜绪氛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涝影。 院中可真熱鬧,春花似錦争占、人聲如沸燃逻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)伯襟。三九已至,卻和暖如春握童,著一層夾襖步出監(jiān)牢的瞬間姆怪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工澡绩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稽揭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓肥卡,卻偏偏與公主長(zhǎng)得像溪掀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子步鉴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

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

  • unsafe 包簡(jiǎn)單說明 unsafe揪胃,顧名思義,是不安全的氛琢,Go定義這個(gè)包名也是這個(gè)意思喊递,讓我們盡可能的不要使用...
    Gopherzhang閱讀 1,512評(píng)論 8 3
  • Lua 5.1 參考手冊(cè) by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,812評(píng)論 0 38
  • 原文地址:在 Go 中恰到好處的內(nèi)存對(duì)齊 問題 在開始之前,希望你計(jì)算一下 Part1 共占用的大小是多少呢阳似? 輸...
    EDDYCJY閱讀 1,116評(píng)論 1 11
  • 一 我不信愛情的存在撮奏,卻相信兩個(gè)人在風(fēng)雨同舟调鲸,共同經(jīng)歷或困苦或甜蜜之后所擁有的親密感盛杰。 關(guān)于七夕最初的記憶,是大奶...
    治愈成長(zhǎng)閱讀 411評(píng)論 2 2
  • 前一段時(shí)間忽然想到同理心這個(gè)詞藐石,百度一下大概意思就是說要從對(duì)方的心理才揣度問題即供,而不是自我出發(fā),以己度人于微。比如將心...
    墨韻書香閱讀 989評(píng)論 7 0