这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
一、第四节课重点内容:
-
自动内存管理
-
Go 内存管理及优化
-
编译器和静态分析
-
Go 编译器优化
二、详细内容:
-
自动内存管理
自动内存管理又叫垃圾回收,主要是为了管理动态内存。所以它包括三个任务:1.为新对象分配内存 2.找到存活对象 3.回收死亡对象空间。 从管理过程来看,主要为三个不同部分,用户程序(Mutator)、分配器(Allocator)及 回收器(Collector)(与c/c++不同,严格意义上这哥俩没有GC)。
具体来说,就是首先需要找出哪些数据还存活着,而哪些数据是不再被需要的(也就是垃圾)。这里可以使用引用计数方法,将没有再被任何东西引用的对象视为可回收垃圾。当对象被创建或者被引用时候内部会存在一个计数器记录它的个数,当它个数为0,即可回收,可参考c++11的智能指针。但同时存在循环引用导致不安全问题(起码c++的share_ptr是这样)。所有又有了追踪垃圾回收。当然还可以使用分代GC。
-
Go内存管理及优化
Go是基于提前分块的方法(感觉有点像内存池)。
- Go以Span为单位向系统申请内存,申请到的Span可能只有一个Page,也可能有N个Page。Span中的Page可以被划分为一系列小对象,也可以整体当做中对象或者大对象分配。Go使用了基于tcmalloc的三层框架缓存。结合Go的GMP模型来看,每个mcache作为一个缓存与一个P进行绑定,通过P访问mcache缓存中的对象。当用户程序申请小对象内存时,mcache会查找tcmalloc的三层框架的前端层,有符合条件的就直接返回,否则向中端层申请内存来重新填充(大部分情况下,前端缓存都能满足用户程序的需求)。同时,mcache只支持单线程访问,所以不需要加锁,避免了加锁带来的性能损耗。
- 由于Go内存分配存在分配路径过长,以及小对象过多问题,优化方案使用Balanced GC(要有balance)。
-
编译器和静态分析(个人感觉了解就好)
废话不多说,课件的图一看便知编译器结构。
-
Go编译器优化
主要分为:
-
函数内联(学过c++的都知道吧)。将被调用函数的函数体的副本替换到调用位置上,同时可以重写代码反映参数的绑定。
-
逃逸分析,分析代码中指针的动态作用域,即指针何时可以被访问。
-