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

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

Does go use something like space padding for structs?

问题

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

  1. type Something struct {
  2. anInteger int16 // 2 bytes
  3. anotherInt int16 // 2 bytes
  4. yetAnother int16 // 2 bytes
  5. someBool bool // 1 byte
  6. } // 我预期总共是7个字节
  7. type SomethingBetter struct {
  8. anInteger int16 // 2 bytes
  9. anotherInt int16 // 2 bytes
  10. yetAnother int16 // 2 bytes
  11. someBool bool // 1 byte
  12. anotherBool bool // 1 byte
  13. } // 我预期总共是8个字节
  14. type Nested struct {
  15. Something // 一开始预期是7个字节
  16. completingByte bool // 1 byte
  17. } // 一开始预期是8个字节

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

  1. Something -> 8 bytes
  2. SomethingBetter -> 8 bytes
  3. 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:

  1. type Something struct {
  2. anInteger int16 // 2 bytes
  3. anotherInt int16 // 2 bytes
  4. yetAnother int16 // 2 bytes
  5. someBool bool // 1 byte
  6. } // I expected 7 bytes total
  7. type SomethingBetter struct {
  8. anInteger int16 // 2 bytes
  9. anotherInt int16 // 2 bytes
  10. yetAnother int16 // 2 bytes
  11. someBool bool // 1 byte
  12. anotherBool bool // 1 byte
  13. } // I expected 8 bytes total
  14. type Nested struct {
  15. Something // 7 bytes expected at first
  16. completingByte bool // 1 byte
  17. } // 8 bytes expected at first sight

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

  1. Something -> 8 bytes
  2. SomethingBetter -> 8 bytes
  3. 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位)。数据总线大小、指令大小、地址大小通常是字长的倍数。
例如,假设有以下结构体:

  1. type data struct {
  2. a bool // 1字节
  3. b int64 // 8字节
  4. }

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

  1. p: 填充
  2. +-----------------------------------------+----------------+
  3. | 1字节bool | p | p | p | p | p | p | p | int-64 |
  4. +-----------------------------------------+----------------+
  5. 第一个8字节 第二个8字节

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

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

现在更好了:

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

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

英文:

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:

  1. type data struct {
  2. a bool // 1 byte
  3. b int64 // 8 byte
  4. }

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>

  1. p: padding
  2. +-----------------------------------------+----------------+
  3. | 1-byte bool | p | p | p | p | p | p | p | int-64 |
  4. +-----------------------------------------+----------------+
  5. first 8 bytes second 8 bytes

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

  1. type data struct {
  2. a string // 16 bytes size 16
  3. b int32 // 4 bytes size 20
  4. // 4 bytes padding size 24
  5. c string // 16 bytes size 40
  6. d int32 // 4 bytes size 44
  7. // 4 bytes padding size 48 - Aligned on 8 bytes
  8. }

Now It's better:

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

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:

确定