Go语言学习8 | 青训营笔记

76 阅读2分钟

这是我参加「第五届青训营」的第8天

Go内存管理

1.分块

目的:为对象在heap上分配内存

提前将内存分块

  1. 调用系统调用mmap()想OS申请一大块内存
  2. 先将内存划分为大块,称作mspan
  3. 再将大块继续划分为特定大小的小块,用于对象分配

mspan的类型

nocan mspan:分配不含指针的对象,GC不需要扫描 scan mspan:分配包含指针的对象,GC需要扫描

对象分配

根据对象的大小,选择最合适的块返回

2.缓存

TCMalloc:用于快速为对象分配空间

图片.png GMP模型中,每个p包含一个mcache用于快速分配,用于为绑定于p上的G分配对象;mcache管理一组mspan;当mcache中的mspan分配完毕时,向mcentral申请带有未分配块的mspan,当mspan中没有分配的对象,mspan会被缓存在mcentral中,而不是立刻释放并归还给OS。

Balanced GC

  • 每个G都绑定一大块内存(1KB),称作GAB
  • GAB用于noscan类型的小对象(<128B)分配
  • GAB对于Go内存管理来说是一个对象

本质:将多个小对象的分配合并成一次大对象的分配

Go 编译器优化

编译器的结构

分析部分(前端)

  • 语法分析,生成语素
  • 语法分析,生成语法树
  • 语义分析,收集类型信息,进行语义检查
  • 中间代码生成,生成IR

综合部分(后端)

  • 代码优化,生成优化后的IR
  • 代码生成,生成目标代码

函数内联

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

  • 优点:消除函数调用开销,例如传递参数,保存寄存器等,将过程间分析转化为过程内分析,帮助其他优化,例如逃逸分析
  • 缺点:函数体变大,instruction cache不友好,编译生成的Go镜像变大