Go垃圾回收

GC原理

现代高级编程语言管理内存的方式分为两种:自动和手动,像 C、C++ 等编程语言使用手动管理内存的方式,
工程师编写代码过程中需要主动申请或者释放内存;
而 PHP、Java 和 Go 等语言使用自动的内存管理系统,有内存分配器和垃圾收集器来代为分配和回收内存,
其中垃圾收集器就是我们常说的 GC。
主流的垃圾回收算法包含”引用计数“和”追踪式垃圾回收“,go的三色标记法就是追踪式垃圾回收的一种。

在垃圾回收中,应用程序称为Mutator,内存分配器称为Allocator,垃圾回收器称为Collector,内存堆称为Heap。

Mark & Sweep(标记和清除)

垃圾回收包含Mark(标记)和Sweep(清除)这两个阶段,有两个术语:

  • STW:即stop the word,在GC的一些阶段需要停止所有的应用程序以确定当前的引用关系,是GC算法优化的重点。
  • Root对象:指不需要通过其他对象就可以直接访问到的对象,如全局对象、栈对象中的数据等。
    通过root对象,可以追踪到其他存活的对象。

传统的Mark & Sweep大致流程:

  1. stop the world: 停止所有应用程序的运行
  2. Mark: 通过Root对象和Root直接间接访问到的对象来寻找所有可达对象,并进行标记
  3. Sweep: 对堆对象进行迭代,未标记的对象加入freelist用于再分配
  4. start the world:程序重新运行
    这个算法最大的缺陷就是GC期间整个程序完全停止,需要在mark和sweep的整个阶段STW。

之后引入并发的GC概念,实现了:

  • mark或sweep步骤可以多个协程同时进行
  • 应用程序mutator可以和垃圾收集collector同时运行

go1.3之后,分离了标记和清除操作,使得mark阶段仍然需要STW,但标记后的sweep和程序可以同时运行。
go1.5之后,标记采用三色标记,标记和清扫都是并发执行,但标记阶段的前后需要 STW 一定时间来做 GC 的准备工作和栈的re-scan。

三色标记法

三色标记将对象标记黑、灰、白三种颜色,大致流程是:
一开始所有对象是白色,从root对象开始标记为灰色,之后从灰色对象列表中开始,将灰色标记为黑色,将其引用的对象再标记为灰色,
直到最后所有引用的对象都是黑色,未引用的数据为白色。
标记结束后,黑色为内存中正在使用的对象,白色是要回收的对象。

Write Barrier(写屏障)

1.5版本在标记过程中使用三色标记法,标记和清扫都并发执行的,但标记阶段的前后需要 STW 一定时间来做GC 的准备工作和栈的 re-scan。
在并发的垃圾回收中,要保证最后的正确性,必须要满足两种三色不变性的一种:
强三色不变性:黑色对象不会指向白色对象,只会指向灰色对象或者黑色对象。
弱三色不变性:黑色对象指向的白色对象必须包含一条从灰色对象经由多个白色对象的可达路径。

  • Write Barrier - Dijkstra 写屏障
    插入屏障拦截将白色指针插入黑色对象的操作,标记其对应对象为灰色状态,这样就不存在黑色对象引用白色对象的情况了,满足强三色不变式,在插入指针 f 时将 C 对象标记为灰色。

  • Write Barrier - Yuasa 删屏障

也是拦截写操作,是通过”保护灰色对象到白色对象的路径不会断“来实现的。

  • 混合屏障

STW

在 “Stop the World” 阶段, 当前运行的所有程序将被暂停, 扫描内存的 root 节点和添加写屏障 (write barrier) 。
Pacing 超过100%内存或者两分钟没有GC会强制触发GC。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值