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