前言
垃圾回收是指对不再使用的内存资源进行自动回收的功能。C++等语言中使用的是手动管理,而Go中则是自动管理。Go的垃圾回收机制主要是三色标记法,可以减少因垃圾回收导致程序暂停的影响。本文主要是学习这个机制。
关于Golang的堆栈内存
C++种,堆内存需要通过new
、delete
等关键字手动管理,栈内存则是编译器自动管理。
而在Golang中,堆栈内存均为编译器进行管理,此文所提到的三色标记法就是堆内存管理的方法。 栈内存仅通过FILO,不需要GC机制。
本文学习的三色标记法,是堆内存管理。
前身——标记清除法
在三色标记法之前,Go采取的是标记清除法
进行垃圾回收处理。
这个方法很好理解,就是通过STW
(简单理解为暂停整个程序),然后对所有对象进行标记与回收。
此方法最大弊端就是在整个GC期间需要STW,将整个程序暂停。大大影响性能。
三色标记法
概念
三色分别是黑、白、灰三色。
⿊⾊:活跃的内存块
⽩⾊:代表最终需要清理的对象内存块
灰⾊:待处理的内存块
流程
(1)将所有对象都置为⽩⾊
(2)扫描出所有的可达(可以搜寻到的)对象,也就是还在使⽤的,不需要清理的对象,标记为灰⾊,放⼊待处
理队列
(3)从队列中提取灰⾊对象,将其引⽤对象标记为灰⾊放⼊队列,将⾃⾝标记为⿊⾊。(需重复执行此步)
(4)有专有的锁监视对象内存修改
(5)在完成全部的扫描和标记⼯作之后,剩余的只有⿊⾊和⽩⾊,分别代表活跃对象与回收对象
(6)清理所有的⽩⾊对象
- 初始阶段所有对象都是⽩⾊
- 从root根出发扫描根对象,将它们引⽤到的对象都标记为灰⾊,其中root区域主要是当前程序运⾏到的栈和全局数据
区域,是实时使⽤到的内存 - 将灰⾊对象标记为⿊⾊,分析该灰⾊对象是否引⽤了其他对象,如果有引⽤其他对象,就将引⽤的对象标记为灰⾊
- 不断分析灰⾊对象,直到灰⾊对象队列为空,此时⽩⾊对象即为垃圾,进⾏回收
GC的触发机制
- 内存分配量达到阈值:每次内存分配前都会检查当前内存分配量是否达到阈值,如果达到则触发GC, 阈值=上次GC
时的内存分配量 * 内存增长率 - 定时触发GC:默认情况下两分钟触发⼀次GC,可由runtime中的参数声明
- ⼿动触发GC:可以在代码中通过使⽤runtime.GC()来⼿动触发
参考资源
本文学习主要参考自公众号:代码随想录,其知识星球的PDF资源,力荐!
同时参考了以下文章:
https://draveness.me/golang/docs/part3-runtime/ch07-memory/golang-garbage-collector/#%E6%A0%87%E8%AE%B0%E6%B8%85%E9%99%A4
https://community.apinto.com/d/34057-golang-gc