Go面试看这里了~(三十)

161 篇文章 12 订阅

原文地址:Go面试看这里了~(三十)

1、内存对齐?

内存是按照成员的定义顺序来依次分配内存,第一个成员偏移量是0,其余每个成员的偏移量为指定数的整数倍数,如此进行内存分配叫做内存对齐。

2、内存对齐原因?

原因有两点,首先就是平台原因,因为并不是所有硬件平台都能访问任意地址上的任意数据,有的会直接报错的,像有的cpu读取4个字节数据,要是没有内存对齐,从1开始,那内存就需要把0-7字节的全部取出来,再剔除掉1/5/6/7,增加了额外的操作,cpu不一定能这么搞,自然就报错,第二个就是性能原因,访问未对齐的内存,需要访问两次,如果对齐的话就只需要一次,像取int64,按照8个位对齐好之后,获取的话直接就是获取8个字节就好,边界好判断。

3、内存对齐原则?

原则有二,其一是具体类型,对齐值=min(编译器默认对齐值,类型大小Sizeof长度),其二是struct每个字段内部对齐,对齐值=min(默认对齐值,字段最大类型长度)。

4、内存对齐案例分析?

来看个案例:

func main() {
  fmt.Println(unsafe.Sizeof(struct {
    i8  int8
    i16 int16
    i32 int32
  }{}))
  fmt.Println(unsafe.Sizeof(struct {
    i8  int8
    i32 int32
    i16 int16
  }{}))
}

输出结果为:

8
12

结构体是平时常用的,由上述输出可看出,相同的成员,不同的排列顺序,需要用到的内存不一致,原因很简单,需要内存对齐的话,因为最大是int32,所以最终结果得是4个字节的倍数才能对齐,当8-16-32的时候,内存存储类似这样|x-xx|xxxx|,当8-32-16的时候,内存存储类似这样|x—|xxxx|xx–|,结果就不言而喻了。

来看使用内存对齐的案例:

type Test struct {
  i8  int8
  i16 int16
  i32 int32
}


func main() {
  var t = new(Test)
  // 从0开始
  var i8 = (*int8)(unsafe.Pointer(t))
  *i8 = int8(10)
  
  // 偏移int8+1的字节数,注意这里有个1!!!
  var i16 = (*int16)(unsafe.Pointer(uintptr(unsafe.Pointer(t))+ uintptr(1)  + uintptr(unsafe.Sizeof(int8(0)))))
  *i16 = int16(10)

  // 偏移int8+1+int16+的字节数,注意这里有个1!!!
  var i32 = (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) + uintptr(1) + uintptr(unsafe.Sizeof(int8(0))+uintptr(unsafe.Sizeof(int16(0))))))
  *i32 = int32(10)
  fmt.Println(*t)
}

上述代码对结构体Test通过指针计算的方式进行赋值,Test内存情况类似这样|x-xx|xxxx|,输出结果为【{10 10 10}】,unsafe.Alignof(t.i16)意为获取对齐值,unsafe.Offsetof(t.i16)意为获取偏移值。

5、内存对齐优化Go程序?

方式有二,其一是根据计算对齐值对struct进行成员顺序的拼凑,可以一定程度上缩小struct占用的内存,其二则为通过分析偏移量和对齐值,准确计算每个成员所偏移的位数,避免算错。

至此,本次分享就结束了,后期会慢慢补充。

以上仅为个人观点,不一定准确,能帮到各位那是最好的。

好啦,到这里本文就结束了,喜欢的话就来个三连击吧。

扫码关注公众号,获取更多优质内容。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值