内存对齐
32位系统,一次可以取32位数据,也就是4字节,64位是8字节,即32为操作系统中内存是4字节对齐,而对于64为操作系统是8字节对齐
目的:
内存对齐的目的是为了能够快速的访问内存进行数据存取,但是会损耗内存,即空间换时间
首先:
package main
import (
"fmt"
"reflect"
"unsafe"
)
type W struct {
b byte
i int32
j int64
}
func main() {
var w W = W{1, 2, 3}
//在struct中,它的对齐值是它的成员中的最大对齐值。
fmt.Printf("%v, %v, %v, %v, %v, %v, %v, %v\n", unsafe.Alignof(w), unsafe.Alignof(w.b), unsafe.Alignof(w.i), unsafe.Alignof(w.j),
unsafe.Sizeof(w), unsafe.Sizeof(w.b), unsafe.Sizeof(w.i), unsafe.Sizeof(w.j))
}
D:\go-project\pkg\demo>go run demo.go
8, 1, 4, 8, 16, 1, 4, 8
可以看出上述代码跑出来的结果是最大8字节对齐的即64为操作系统,其中b为1字节对齐、i为4字节对齐,j为8字节对齐,其中W为结构体内参数最大的参数做内存对齐,而sizeof计算的是结构体一共占用多少字节数,这里面的计算就涉及到内存对齐,首先计算参数b和i,这两个参数总和加起来少于w结构体的内存对齐的字节数,所以这两个字节占用8字节,而j占用8字节,那么w一共16字节
但是如果结构体是下面这样写的:
type W struct {
i int32
j int64
b byte
}
那么i占8个字节,j占8个字节,b占8个字节,一共24个字节数
下面来聊聊内存对齐最底层原理:
首先针对64位寻址的内存,一个内存是由若干个黑色的内存颗粒构成的。每一个内存颗粒叫做一个chip。每个chip内部,是由8个bank组成的,如果是32位就是4片,如下:
而每一个bank是一个二维平面上的矩阵,矩阵中每一个元素中都是保存了1个字节,也就是8个bit。
内存中的8个bank是可以并行工作的,即当我们寻址0x0000-0x0007时,寻址的是下面8*8=64bit,如果是0x0000时,我们只读取blank0上的一个字节,那么如果读0x0003的时候那么就变成了0x0000+3两次寻址