什么是内存对齐?
现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问, 这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是内存对齐。
为什么要内存对齐
1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
如32位的字长为4字节,CPU读取每次都是以字长访问的,即每次访问4字长。如果有两个数据A,B都是3字节即,AAABBB,那么在没有内存对齐的情况下CPU就需要访问两次。先访问AAAB取出B,再访问BB。如果内存对齐了,内存排列会变成AAAxBBBx那么直接访问一次就可以了。
对齐规则-Go
1.具体类型,对齐值=min(编译器默认对齐值,类型大小Sizeof长度)
2.struct每个字段内部对齐,对齐值=min(默认对齐值,字段最大类型长度)
例子:
func main() {
fmt.Println(unsafe.Sizeof(struct {
i8 int8
i16 int16
i32 int32
}{}))
fmt.Println(unsafe.Sizeof(struct {
i8 int8
i32 int32
i16 int16
}{}))
}
输出:
8
12
分析:
int8为1字节,int16为2字节,int32为4字节。字段最大类型长度为4。
当8-16-32的时候,类似这样|x-xx|xxxx|。
当8-32-16的时候,类似这样|x—|xxxx|xx–|。
总结
编译器为了兼容和时间效率,在分配内存的时候需要进行内存对齐。在写struct的时候,尽量将小的数据排列在一起,减少struct占用的内存。