内存对齐 32位系统,一次可以取32位数据,也就是4字节,64位是8字节,即32为操作系统中内存是4字节对齐,而对于64为操作系统是8字节对齐
目的: 内存对齐的目的是为了能够快速的访问内存进行数据存取,但是会损耗内存,即空间换时间
首先:
package mainimport (
"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
}
【go语言|GO语言-内存对齐】那么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两次寻址

文章图片
推荐阅读
- go语言|Go mod 使用私有git仓库依赖包
- 1000道程序员常见问题解析|一文搞懂Linux 内存管理原理
- Redis笔记(简介源码安装常用命令配置文件内存管理)
- Linux 内核 内存管理分区伙伴分配器 ③ ( 备用内存区域列表 | ZONELIST_FALLBACK 枚举 | zoneref 结构体 | 备用内存区域借用物理页规则 )
- Linux 内核 内存管理物理分配页 ② ( __alloc_pages_nodemask 函数参数分析 | __alloc_pages_nodemask 函数分配物理页流程 )
- Linux 内核 内存管理RCU 机制 ① ( RCU 机制简介 | RCU 机制的优势与弊端 | RCU 机制的链表应用场景 )
- Linux 内核 内存管理优化内存屏障 ④ ( 处理器内存屏障 | 八种处理器内存屏障 | 通用内存屏障 | 写内存屏障 | 读内存屏障 | 数据依赖屏障 | 强制性内存屏障
- Linux 内核 内存管理RCU 机制 ② ( RCU 机制适用场景 | RCU 机制特点 | 使用 RCU 机制保护链表 )
- Go语言 unsafe.Pointer 浅析