Go的内存管理分析 | 青训营笔记

120 阅读3分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 4 天

Garbage Collection

垃圾回收机制是Go语言的特性,别名:自动内存管理

我们在C/C++中,常会遇到malloc或者new [type]的情况,这就是在向系统申请动态内存。动态内存存放在堆(Heap)中,如果到程序末尾不需要再用到这块动态内存/变量,则需要通过free操作完成内存回收,这才是一个健全的代码内存管理流程。

可是在开发过程中,会用到各种各样的申请动态内存的情况,尤其是处理不确定的数据时,例如Go语言的new make关键字,如果仍然要在末尾进行各种各样的free操作,难免会有遗漏而且不能完全保证内存的安全。

垃圾回收机制在Java语言中广受流传,而Go语言同样也有内存回收机制。

GC的任务与要求

  • 为新对象分配空间
  • 找到存活对象
  • 回收死亡对象的内存空间

在GC中有许许多多的问题,其中就有double free problemuse after free problem

double free problem:同一块内存在第一次被释放以后,第二次仍然释放(释放空内存)

use after free problem:一块内存在被释放以后,又遇到了对这块内存进行访问的操作。(读到空内存)

GC design history

负责GC的主要有两个线程。

Mutator线程:分配新对象,修改对象指向关系

Collector线程:找到存活对象,回收死亡对象的内存空间

最初以Serial GC方式进行垃圾回收。在程序中会强行Pause,然后进行单线程的Collect

image.png

后来又有Parallel GC,顾名思义,会通过多条Collector线程进行回收,但是缺点是还是会造成程序Block

image.png

现有的Concurrent GC,可以不用阻塞程序运行,并且分为Mutator和Collector两类线程进行内存回收。

image.png

哪种变量才会被回收?

Go使用三色标记法对垃圾内存进行判断。

image.png

图片来源 (https://juejin.cn/post/6844903917650722829)

  1. 初始状态所有对象都是白色。
  2. 从root根出发扫描所有根对象(下图a,b),将他们引用的对象标记为灰色(图中A,B)
  3. 分析灰色对象是否引用了其他对象。如果没有引用其它对象则将该灰色对象标记为黑色(上图中A);如果有引用则将它变为黑色的同时将它引用的对象也变为灰色(上图中B引用了D)
  4. 重复步骤3,直到灰色对象队列为空。此时白色对象即为垃圾,进行回收。

评价GC算法

image.png

图片来源:青训营内部课件

编译器和静态分析

编译器结构

image.png

图片来源:青训营内部课件

静态分析

静态分析:不执行程序代码,推导程序的行为。

过程内分析:仅在函数内部进行分析

过程间分析:函数调用时参数传递和返回值的控制流、数据流

但是过程间分析要考虑多条函数的跳转,比较复杂。

GO编译器优化

函数内联

Go通过内联的方式减少函数调用开销,还可以将过程间分析转化为过程内分析

Beast Mode

函数内联受到的限制比较多,如interface,defer等,限制了函数内联,并且内联策略非常保守。Beast Mode调整了函数内联的策略,使更多函数被内联。这样做降低了函数调用开销,同时引入了逃逸分析

逃逸分析

image.png

图片来源:青训营内部课件