Golang底层原理剖析之内存对齐
为什么要内存对齐
假设数据总线64位,每次读取连续的8个字节,所以每次读取的地址一定是8的倍数,如果非要错开一个地址,由于最后一个字节对应的位置与前7个不同,不能在一次读取中读完整,那么就需要分两次读,把两次结果拼接起来拿到所需数据,这必然会影响性能。
如何内存对齐
所以为保证程序顺利高效的运行,编译器会把各种类型的数据安排到合适的地址并占用合适的长度,这就是内存对齐,每种类型的对齐值就是它的对齐边界,内存对齐要求数据存储地址以及占用的字节数都要是它的对齐边界的倍数
因此,int32要错开两字节,从4开始存,不能紧接着从2开始,那么,怎么确定每种类型的对齐边界呢?
数据类型的对齐边界,取类型大小与平台最大对其边界(字长)中较小的那个
结构体内存对齐
怎么确定一个结构体的对齐边界呢?首先确定每个成员的对齐边界,假设在64位平台上,取其中成员内存对齐边界中对大的那个,这就是这个结构体的对齐边界
存储这个结构体的起始地址,是对齐边界的倍数,结构体的每个成员在存储时,把这个起始地址当作地址0,然后再用相对地址来决定自己放在哪,a成员要对齐1字节,0%1=0,所以a放在0地址,而b要对齐到八字节 ,但是下面的地址对8取模不等于0,所以b要在8地址存储,而c要对齐到4字节,16%4=0,接下来的位置就刚好,d对齐了2字节,位置也刚好,至此已经用了22个字节了
结构体整体占用字节数需要是结构体类型对齐边界(此处是8)的倍数,不够的话要往后扩张一下,所以它要扩充到相对地址23这里,最终这个结构体类型的大小就是24字节,至此,对齐完成