这是我参加「第五届青训营」的第8天
Go内存管理
1.分块
目的:为对象在heap上分配内存
提前将内存分块
- 调用系统调用mmap()想OS申请一大块内存
- 先将内存划分为大块,称作mspan
- 再将大块继续划分为特定大小的小块,用于对象分配
mspan的类型
nocan mspan:分配不含指针的对象,GC不需要扫描 scan mspan:分配包含指针的对象,GC需要扫描
对象分配
根据对象的大小,选择最合适的块返回
2.缓存
TCMalloc:用于快速为对象分配空间
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镜像变大