Open geektutu opened 3 years ago
如果内存对齐只是涉及更改顺序的话,go 为什么不在编译时和运行时自动进行对齐呢? 如果编译时存在跨平台优化问题,那么运行时应该可以确定如何对齐最优吧。
@OhYee 如果内存对齐只是涉及更改顺序的话,go 为什么不在编译时和运行时自动进行对齐呢? 如果编译时存在跨平台优化问题,那么运行时应该可以确定如何对齐最优吧。
Go在编译的时候会自动内存对齐,就是上面说的,不同顺序占用的内存不一样,这就是自动对齐的结果。Go如果更改了结构体的顺序,如果在数据传输的时候,如何正确的读取到结构体的内容呢?
@zhcoders 明白了,没考虑到跨平台数据传输的问题,感谢 👍
字节对齐这个概念有两处需要强调:
“b 是第二个字段,对齐倍数为 2,因此,必须空出 1 个字节,偏移量才是 2 的倍数,从第 2 个位置开始占据 2 字节。” 为什么要空一个字段呢?
@qilinworld “b 是第二个字段,对齐倍数为 2,因此,必须空出 1 个字节,偏移量才是 2 的倍数,从第 2 个位置开始占据 2 字节。” 为什么要空一个字段呢?
为了减少CPU读取次数,是一种空间换时间的做法。
比如demo1,按照2的倍数,第一次读取a(实际占用1字节)读两个字节,第二次读取b(实际占用2字节)也是两个字节,第三次读取c(实际占用4个字节)前两个字节,第四次读取c后两个字节,共读取4次。
demo2也是,按照c的倍数4对齐,第一次读取a(实际占用1字节)四个字节,第二次读取c四个字节,第三次读取b(实际占用2字节)四个字节,共读取3次。
如果按照a的1倍对齐,那么demo1里CPU就要读取a(1次)+b(2次)+c(3次)=6次,demo2也一样。
但我在本机看到demo1和demo2的对齐倍数都是4
对于 struct 结构体类型的变量 x,计算 x 每一个字段 f 的 unsafe.Alignof(x.f),unsafe.Alignof(x) 等于其中的最大值。
根据上面的规则,demo1中的b字段的对齐:b 是第二个字段,对齐倍数为 2,因此,必须空出 1 个字节,偏移量才是 2 的倍数,从第 2 个位置开始占据 2 字节。
应该将对齐倍数看做4才对吧?
空结构体填充不是字节对齐的问题
"即当 struct{} 作为结构体最后一个字段时,需要内存对齐。因为如果有指针指向该字段, 返回的地址将在结构体之外,如果此指针一直存活不释放对应的内存,就会有内存泄露的问题(该内存不因结构体释放而释放)。"
这段话不太理解,“因为如果有指针指向该字段, 返回的地址将在结构体之外”,是对齐的时候,还是非对齐的时候产生此现象。以及为什么返回的地址在结构体之外?能否举个具体的例子呢?
@HeliumTang 对于 struct 结构体类型的变量 x,计算 x 每一个字段 f 的 unsafe.Alignof(x.f),unsafe.Alignof(x) 等于其中的最大值。 根据上面的规则,demo1中的b字段的对齐:
b 是第二个字段,对齐倍数为 2,因此,必须空出 1 个字节,偏移量才是 2 的倍数,从第 2 个位置开始占据 2 字节。
应该将对齐倍数看做4才对吧?
到b字段的时候最大值是b只占用2字节没问题的,到c字段最大值为c占用4字节没问题的
博主,请问您的这个博客站点是如何搭建的?
有联系方式吗
兔兔, 这个地方感觉有点模糊,
因为如果有指针指向该字段, 返回的地址将在结构体之外,如果此指针一直存活不释放对应的内存,就会有内存泄露的问题(该内存不因结构体释放而释放)。
我用fieldalignment检测,并没有提示demo2需要优化,是什么原因呢
https://geektutu.com/post/hpg-struct-alignment.html
Go 语言/golang 高性能编程,Go 语言进阶教程,Go 语言高性能编程(high performance go)。本文介绍了结构体(struct)占用的内存空间如何计算,为什么要字节对齐/内存对齐,Go 语言中的大小和对齐保证(size and alignment guarantees),字节对齐和安全访问(原子访问)的关系,以及如果利用内存对齐的规律减小 struct 内存占用。