Please enable Javascript to view the contents

Golang-中级-三色标记

 ·  ☕ 3 分钟

GC算法介绍

三色标记清理

程序 = 一些对象的根节点的集合
初始对象为白色

  1. 遍历所有根节点对象(有的在栈,有些在堆),置为灰色;
  2. 遍历所有灰色对象,灰色变为黑色,灰色引用的白色变为灰色;
  3. 直至灰色队列为空,标记结束。(黑色为可达,白色不可达)

屏障

读屏障:是在读对象时插入屏障,对性能影响很大,不考虑。

  • 插入写屏障

原理:强三色不变式(避免黑->白的直接引用)
实现:黑色对象添加白色对象,那么将白色对象改为灰色
堆上直接插入写屏障进行标记,完成后对栈进行stw暂停保护(阻塞对栈上对象读写),然后对象全复位为白色进行三色标记。之后执行gc
缺点:堆标记结束后,需要STW来重新扫描栈,标记栈上引用的白色对象的存活。

  • 删除写屏障(删除引用时引入屏障)
    原理:弱三色不变式(避免丢失灰->白的引用)
    实现:当灰色删除到白色对象引用时,将白色对象直接变为灰色
    缺点:删除屏障回收精度低(GC开始时STW扫描堆栈来记录初始快照,这个过程会保护开始时刻的所有存活对象。)

  • 混合写屏障(屏障在gc,只有执行gc时触发)
    原理:变形弱三色
    实现:
    (1)GC开始时,将栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW)。
    (2)GC期间,任何在栈上创建的新对象,均为黑色。
    (3)被删除的对象标记为灰色。
    (4)被添加的对象标记为灰色。

golang采取的垃圾清理策略

标记清理 → 三色标记 → 三色+混合写屏障

三色标记法+混合写屏障机制,栈空间不启动屏障机制,堆空间启动屏障机制。整个过程几乎不需要STW(标记完-清理前,执行housekeeping 如刷新mcache),效率较高。

栈和堆的区别

go内存会分成堆区(Heap)和栈区(Stack)两个部分。

程序在运行期间可以主动从堆区申请内存空间,这些内存由内存分配器分配并由垃圾收集器负责回收。

栈区的内存由编译器自动进行分配和释放,栈区中存储着函数的参数以及局部变量,它们会随着函数的创建而创建函数的返回而销毁

golang的GC什么时候触发?

1、阀值:默认内存扩大一倍(是上次清扫时的两倍),启动GC;
2、定期:默认2min触发一次GC
3、手动启动GC src/runtime/proc.go:forcegcperiod;手动:runtime.gc()

GC说明

垃圾回收过程中,主要包含这几个角色:应用程序(mutator)、内存分配器(Allocator)、内存堆(heap)、垃圾回收器(collector)。

主流垃圾回收算法分为两类: 引用计数(缺陷)、追踪式垃圾回收。

Golang的三色标记法、Java的新老生代都属于追踪式垃圾回收。

追踪式垃圾回收:

主要基于 Mark & Sweep 实现。Mark & Sweep 两个阶段: 标记(Mark)、清除(Sweep)。

概念:

  • STW: Stop The Word, GC的一些阶段需要停止所有的应用程序(mucator)

  • Root:

分享

Hex
作者
Hex
CloudNative Developer

目录