内存对齐
目录
计算机总线中有一个 数据总线,用来传输内存上的数据到寄存器中,数据总线大小决定了一次能传输多个数据,比如32位
总线一次能传输4字节
,字长就是4字节
,如果需要取一个8字节的数据就需要传输两次,64位
总线一次能传输8字节
,字长就是8字节
,取一个8字节的数据只需要一次传输即可,所以CPU取数据都是以数据总线宽度(也就是CPU字长)为单位来取的
内存对齐就是为了提高CPU获取数据的效率,如果不进行内存对齐可能会增加CPU访问数据的次数
|a|a|a|b|b|b| | | #对齐前
|a|a|a| |b|b|b| | #对齐后
比如a、b各自占用3byte,CPU字长为4byte,不进行内存对齐而采用紧凑的方式存储那么访问a只需要一次,但是访问b就需要进行两次
并且一个struct
的起始地址也是需要从CPU字长的整数倍开始的,同时如果一个struct
的长度不足自身内存对齐边界(属性中长度最长的那个)的整数倍则会进行填充,这是为了在数组中保持struct依然是内存对齐的
因为struct会进行内存对齐,所以我们需要合理的布局struct中各个属性的分布,这样才能有效的减少内存大小
type A struct {
a int8
b int16
c int32
}
type B struct {
a int8
c int32
b int16
}
type C struct {
a int32
c int64
b int8
}
type D struct {
c int64
a int32
b int8
}
func main() {
fmt.Println(unsafe.Sizeof(A{})) // 8
fmt.Println(unsafe.Sizeof(B{})) // 12
fmt.Println(unsafe.Sizeof(C{})) // 24
fmt.Println(unsafe.Sizeof(D{})) // 16
}
在Go中需要结算struct中对齐边界最大的值作为整个结构体的对齐边界