ByteCamp Note 4 内存/分析/优化

118 阅读2分钟

GO内存

GO机制

分块

调用mmap()向OS申请一块大内存,再将内存划分成大块,称为mspan 再将msoan划分为特定大小的小块,用于对象分配

  • noscan mspan 分配不包含指针的对象 -- GC不需要扫描
  • scan mspan 分配包含指针的对象 -- GC需要扫描 根据对象的大小返回内存快

缓存

借鉴TCMalloc: thread caching 每个p包含一个mcache用于快速分配,用于为绑定 与p上的g分配对象 mcache 管理一组mspan 当mcache中的mspan分配完毕,向mcentral申请带有未分配块的mspan 当mspan中没有分配的对象,mspan会被缓存在mcentral中,而不是立即释放并归还给OS

截屏2022-05-14 21.39.15.png

分析和优化

  • 小对象占比较高
  • 分配路径长

Balanced GC

goroutine alloction buffer,使用base, end, top 指针维护
Bump point 风格对象分配:

  • 通过操作指针完成对象分配,简单高效
  • 无需和其他分配请求互斥 看上去有点像c++ 本质上是将多个小对象的分配合并成一次大对象分配
    ❓GAB对象分配导致内存释放被延迟 ✅ 移动GAB中的存活对象
  • 当GAB总大小超过一定阈值,将其中存活的对象复制到另外分配的 Survivor GAB 中
  • 原先的GAB可以释放,避免内存泄漏
  • 本质:用copying GC 的算法管理小对象,根据对象生命周期使用不同的标记和清理策略

编译器

函数内联

将被调用函数的函数体的副本替换到调用位置上,同时重写代码以反映参数的绑定

  • 消除函数调用开销:传参,保存寄存器
  • 将过程间分析转化为过程内分析 缺点
  • 函数体变大,instruction cache不友好
  • 编译生成Go镜像变大

Go限制较多

Beast mode 调整函数内联策略,增加逃逸分析

逃逸分析