[[toc]]
- 如何理解GO GC原理和优化思路
对Golang垃圾回收原理进行剖析,并通过实战样例分析来定位GC问题,从而掌握优化思路。
- 在申请内存的时候,检查当前当前已分配的内存是否大于上次GC后的内存的2倍,若是则触发(主GC线程为当前M)
- 监控线程发现上次GC的时间已经超过两分钟了,触发;将一个G任务放到全局G队列中去。(主GC线程为执行这个G任务的M)
####说明:
-
mark 有两个过程。
- 从 root 开始遍历,标记为灰色。遍历灰色队列。
- re-scan 全局指针和栈。因为 mark 和用户程序是并行的,所以在过程 1 的时候可能会有新的对象分配,这个时候就需要通过写屏障(write barrier)记录下来。re-scan 再完成检查一下。
-
Stop The World 有两个过程。
- 第一个是 GC 将要开始的时候,这个时候主要是一些准备工作,比如 enable write barrier。
- 第二个过程就是上面提到的 re-scan 过程。如果这个时候没有 stw,那么 mark 将无休止。
-
回收过程目前是可以并行执行执行
<<< @/../golang-garbage-collection/gc_m.cpp
Golang GC 垃圾回收算法采用的是三色标记法,原理如下:
1. 初始所有对象都是白色
2. 从root(包含全局指针和goroutine栈上指针)出发扫描所有的可达对象,将可达对象标记为灰色,放入对处理队列
3. 从队列中取出所有的灰色对象,将这轮灰色对象所引用的对象标记为灰色放入队列,并将自己标记成黑色
4. 重复3,直到灰色队列为空。此时剩余的白色对象即为垃圾,执行回收。
-缺点:可能程序中的垃圾产生的速度会大于垃圾收集的速度,这样会导致程序中的垃圾越来越多无法被收集掉。 -解决:go 除了标准的三色收集以外,还有一个辅助回收功能,防止垃圾产生过快手机不过来的情况。这部分代码在 runtime.gcAssistAlloc 中
对于和用户程序并发运行的垃圾回收算法,用户程序会一直修改内存,所以需要记录下来。