Spiga

Go GC回收过程笔记

2020-11-21 11:39:28

Go语言GC算法主要是基于Mark and Sweep (标记清除)算法,在此基础上进行改进和优化。
1). Mark and Sweep(标记清除)算法主要是以下2个步骤:
标记(Mark): 找出所有不可达对象,然后做上标记
清除(Sweep): 回收标记好的对象

标记清除具体步骤如下:
a). 开始标记,程序暂停
b). 找到所有可达对象,并做上标记
c). 标记完成后开始清除未标记的对象
d). 清除完成

2). 标记清除算法存在以下几个问题
a). STW (stop the world) 标记对象的时候程序需要暂停,导致程序出现卡顿 (最主要的问题)
b). 标记需要扫描整个堆
c). 清除对象会产生堆碎片
STW指的是runtime把所有的协程都冻结了,意味着用户逻辑是暂停的,这样所有的对象都不会被修改,这个时候去扫描是绝对安全的。

3). Tri-color Marking
为了解决标记清除算法带来的问题,Go在标记清除算法基础上提出来Tri-color Marking(三色标记法)算法来优化GC过程,大体流程如下:
a). 最开始所有的对象都是白色的
b). GC开始,扫描所有可达的对象,标记为灰色
c). 从灰色对象中找到其引用对象并标记为灰色,自己标记为黑色
d). 监控对象修改,循环上一步骤,直到没有任何灰色对象
e). GC回收白色对象
f). 最后把所有黑色对象变成白色

4). 三色标记法通过2点来优化STW问题
a). 标记操作和用户逻辑并行:
用户逻辑经常会生成或改变对象引用,那如何保证标记和用户逻辑并行呢?Go为了解决这个问题引入了写屏障机制,在GC的过程中会监控对象的内存修改,并对对象进行重新标记,这个时候用户逻辑也可以执行 (实际上是很短暂的STW,然后对对象重新标记),所以标记操作可以做到一定程度和用户逻辑并行。

b). 清除操作和用户逻辑并行:
三色标记法中最后只剩下的黑白两种对象,黑色对象是程序恢复后接着使用的对象,如果不碰触黑色对象,只清除白色的对象,肯定不会影响程序逻辑,所以清除白色对象和用户逻辑可以并行。

通过允许用户逻辑在标记和清除操作上做到并行处理来缩短STW的时间,提升整体GC的性能。