英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论