Go内存对齐对性能的影响
CPU 访问内存时,并不是逐个字节访问,而是以字长为单位。32位CPU的字长是4字节,64位CPU的字长是8字节。
CPU 始终以字长访问内存,如果不进行内存对齐,很可能增加 CPU 访问内存的次数。
-
unsafe.Sizeof
: 返回数据类型需要占用的字节数 -
unsafe.Alignof
: 返回数据类型的对齐系数
type Args struct {
num1 int // int占8字节
num2 int // int占8字节
}
type Flag struct {
num1 int16 // int16占2字节
num2 int32 // int32占4字节
}
func main() {
fmt.Println(unsafe.Sizeof(Args{}))
fmt.Println(unsafe.Sizeof(Flag{}))
}
-
Args
由 2 个int
类型的字段构成,在 64位机器上,一个int
占 8 字节,因此存储一个Args
实例需要 16 字节。 -
Flag
由一个int32
和 一个int16
的字段构成,成员变量占据的字节数为 4+2 = 6,但是unsafe.Sizeof
返回的结果为 8 字节,多出来的 2 字节是内存对齐的结果。
对齐补证
- 对于任意类型的变量 x ,
unsafe.Alignof(x)
至少为 1。 - 对于 struct 结构体类型的变量 x,计算 x 每一个字段 f 的
unsafe.Alignof(x.f)
,unsafe.Alignof(x)
等于其中的最大值。 - 对于 array 数组类型的变量 x,
unsafe.Alignof(x)
等于构成数组的元素类型的对齐倍数。