Go语言是否使用类似空间填充的方式来处理结构体?

huangapple go评论75阅读模式
英文:

Does go use something like space padding for structs?

问题

我在go语言中进行了一些尝试,试图计算和获取结构体对象的大小。我发现了一些有趣的事情,如果你看一下下面的结构体:

type Something struct {
        anInteger        int16 // 2 bytes
        anotherInt       int16 // 2 bytes
        yetAnother       int16 // 2 bytes
        someBool         bool  // 1 byte
} // 我预期总共是7个字节

type SomethingBetter struct {
        anInteger        int16 // 2 bytes
        anotherInt       int16 // 2 bytes
        yetAnother       int16 // 2 bytes
        someBool         bool  // 1 byte
        anotherBool      bool  // 1 byte
} // 我预期总共是8个字节

type Nested struct {
        Something // 一开始预期是7个字节
        completingByte   bool // 1 byte
} // 一开始预期是8个字节

但是,我使用unsafe.Sizeof(...)得到的结果如下:

Something         -> 8 bytes
SomethingBetter   -> 8 bytes
Nested            -> 12 bytes,尽管发现"Something"使用了8个字节,但这可能使用了9个字节

我怀疑go语言做了一种类似于填充的操作,但我不知道它是如何以及为什么这样做的,是否有一些公式或逻辑?如果它使用空间填充,是随机进行的吗?还是基于某些规则?

英文:

I was playing around in go, and was trying to calculate and get the size of struct objects. And found something interesting, if you take a look at the following structs:

type Something struct {
        anInteger        int16 // 2 bytes
        anotherInt       int16 // 2 bytes
        yetAnother       int16 // 2 bytes
        someBool         bool  // 1 byte
} // I expected 7 bytes total

type SomethingBetter struct {
        anInteger        int16 // 2 bytes
        anotherInt       int16 // 2 bytes
        yetAnother       int16 // 2 bytes
        someBool         bool  // 1 byte
        anotherBool      bool  // 1 byte
} // I expected 8 bytes total

type Nested struct {
        Something // 7 bytes expected at first
        completingByte   bool // 1 byte
} // 8 bytes expected at first sight

But the result I got using unsafe.Sizeof(...) was as following:

Something         -> 8 bytes
SomethingBetter   -> 8 bytes
Nested            -> 12 bytes, still, after finding out that "Something" used 8 bytes, though this might use 9 bytes

I suspect that go does something kind of like padding, but I don't know how and why it does that, is there some formula? Or logics? If it uses space padding, is it done randomly? Or based on some rules?

答案1

得分: 2

是的,我们有填充!如果您的系统架构是“32位”,则字长为“4字节”,如果是“64位”,则字长为“8字节”。现在,什么是字长?“字长”是指计算机CPU一次处理的位数(现在通常为32位或64位)。数据总线大小、指令大小、地址大小通常是字长的倍数。
例如,假设有以下结构体:

type data struct {
    a bool     // 1字节
    b int64    // 8字节
}

这个结构体的大小不是9字节,因为当字长为8时,第一个周期,CPU读取1字节的bool值,并为其他成员填充7字节。
想象一下:

p: 填充
+-----------------------------------------+----------------+
| 1字节bool | p | p | p | p | p | p | p |     int-64     |
+-----------------------------------------+----------------+
              第一个8字节                 第二个8字节

为了提高性能,应该将结构体成员按从大到小的顺序排序。
这样的性能不好:

type data struct {
    a string //	16字节			大小16
    b int32  //	 4字节			大小20
    //  		 4字节填充		大小24
    c string //	16字节			大小40
    d int32  //	 4字节			大小44
    //  		 4字节填充		大小48 - 对齐在8字节上
}

现在更好了:

type data struct {
    a string //	16字节			大小16
    c string //	16字节			大小32
    d int32  //	 4字节			大小36
    b int32  //	 4字节			大小40
    //  		 无填充	        大小40 - 对齐在5字节上
}

请参阅这里获取更多示例。

英文:

Yes, we have padding! if your system architecture is 32-bit the word size is 4 bytes and if it is 64-bit, the word size is 8 bytes. Now, what is the word size? "Word size" refers to the number of bits processed by a computer's CPU in one go (these days, typically 32 bits or 64 bits). Data bus size, instruction size, address size are usually multiples of the word size.
<br >For example, suppose this struct:

type data struct {
        a bool     // 1 byte
        b int64    // 8 byte
}

This struct it's not 9 bytes because, when our word size is 8, for first cycle, cpu reads 1 byte of bool and padding 7 bytes for others. <br>
<b>Imagine:</b>

p: padding
+-----------------------------------------+----------------+
| 1-byte bool | p | p | p | p | p | p | p |     int-64     |
+-----------------------------------------+----------------+
              first 8 bytes                 second 8 bytes

For better performance, sort your struct items from bigger to small. <br>
This is not good performance:

type data struct {
	a string //	16 bytes			size 16
	b int32  //	 4 bytes			size 20
	//  		 4 bytes padding	size 24
	c string //	16 bytes			size 40
	d int32  //	 4 bytes			size 44
	//  		 4 bytes padding	size 48 - Aligned on 8 bytes
}

Now It's better:

type data struct {
	a string //	16 bytes			size 16
	c string //	16 bytes			size 32
	d int32  //	 4 bytes			size 36
	b int32  //	 4 bytes			size 40
	//  		 no padding	        size 40 - Aligned on 5 bytes
}

See here for more examples.

huangapple
  • 本文由 发表于 2022年8月3日 01:54:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/73211746.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定