您的位置 首页 golang

golang内存对齐

为什么要内存对齐?

先看个问题:

这个最终会输出多少?是一个1byte(1字节) + int32(4) = 5个字节吗?答案是8。

存取粒度:
首先内存是以字节为单位的,当然处理器不会按照一个字节一个字节来读取数据的,这样效率太低。处理器为了提高读取的效率,可以每次读取一批字节, 这样的一批可以2、4、8、16等等(2^n),这个叫内存存取粒度。假设现在存取粒度是8,那么现在有一个字节,它存在第二个位置上,cpu会把8个都读进来, 然后去掉第一个和后面6个,剩下的就是目标字节。

不对齐有什么问题?
假设现在存取粒度是8,且有两个数据各占5个字节。

  • 不对齐

可以发现第二个数据分布在第一块内存块(0-8)和第二块内存块(8-16)中,那么读取第二块数据的时候,就要读 两次 ,然后剔除第一块内存块的前5位,剔除第二个内存块的后6位,然后组装。

  • 对齐

cpu可以直接切到第二个内存块,一次性读取8个字节,取前5个,剔除后面3个,结束,只需要读取一次。

go内存对齐

go的对齐系数可以通过 unsafe.Alignof 获取,占用长度可以用 unsafe.Sizeof 获取。

  • unsafe.Alignof

官方文档的描述:

  1. 任何类型对齐长度至少为1
  2. 对于struct,对齐长度为内部最大对其长度的那个成员
  3. 对于数组类型,对齐长度是元素类型的长度(比如[2]int8就是int8的长度=1)
  • unsafe.Sizeof

获取类型对齐长度:

对齐优化

  1. 根据unsafe.Alignof 的规则2,得出struct的对齐长度为8
  2. a占用一个字节,对齐长度是8,且a的下一个元素是c,c就占8个字节,所以第一块浪费7个字节
  3. c占用8个字节,占满第二块
  4. b占4字节,第三块浪费4字节

总共占用 24 字节。

我们换下b和c的顺序:

  1. 根据unsafe.Alignof 的规则2,得出struct的对齐长度为8
  2. a占用一个字节,对齐长度是8,且a的下一个元素是b,b占用4个字节,a和b都在第一块,第一块剩余3个字节
  3. c占8字节,第一块剩余的3个不够,占满第二块

总共占用 16 字节。

对于struct类型,合理的成员顺序可以减少内存占用。

欢迎大家关注公众号《假装懂编程》,我将持续输出网络、数据库、go、缓存、架构、面试、程序人生相关文章。

文章来源:智云一二三科技

文章标题:golang内存对齐

文章地址:https://www.zhihuclub.com/99540.shtml

关于作者: 智云科技

热门文章

网站地图