这是我参与「第三届青训营 -后端场」笔记创作活动的第6篇笔记
go内存管理机制及内存管理优化
2.1 go内存分配
- 分块 为对象在heap上分配内存,先提前申请一块大内存,在分成多块小内存,根据对象的大小分配最合适的块返回
- 缓存
p包含mcache为绑定于p上的g分配内存,mcache管理一组mspan,mspan中没有空闲位置时,会向mcentral申请一块未分配的mspan,当一块mspan空时,不会立即释放,而是被缓存到mcentral中
Balanced GC
- GAB:每个g都绑定一大块内存。用于noscan类的内存分配
用base,top,end三个指针维护
GAB对go内存管理是一个对象,优化的本质是将分配多个小对象转化为分配一个对象,当一个gab总大小小于一个阈值时,将其中存活的对象分配到其他gab中,并且可以考虑释放此gab的内存避免内存泄漏。
3. 编译器和静态分析
3.1编译器的结构
1.重要的系统软件
- 识别符合语法和非法的程序,生成正确且高效的代码
2.分析部分(前端)
3.综合部分(后端)
3.2静态分析
定义:不运行程序代码,推导代码的行为
控制流:程序执行的流程
数据流:数据在控制流上的传递
通过分析控制流和数据流确定程序的性质以便优化
3.3过程内分析和过程间分析
前者仅在函数内部分析,后者需要考虑函数调用时传递参数和返回值的控制流和数据流,较为复杂。
4. go编译器优化的基本问题与思路
4.1优化操作
1. 函数内联
对于轻量代码,使用函数内联可以将过程间分析转化为过程内分析,属于正向优化
Beast Mode
调整函数内联的策略,使更多函数被内联,减少函数调用的开销
2. 逃逸分析
分析代码中指针的作用域。从对象分配处沿着控制流,观察对象的数据流。
指针逃逸出当前作用域的原因:
1.作为参数被函数调用
2.传递给全局变量或 goroutine
3.传递给已经逃逸的指针指向的对象
Beast Mode
函数内联拓展函数边界,减少逃逸
未逃逸的对象可以在栈上进行操作,减少在heap上的分配,降低GC负担