返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

3.1.1 注释

发布于 2024-10-12 19:16:03 字数 2044 浏览 0 评论 0 收藏 0

翻译自 1.15 mgc.go 头部注释。

garbage collector

回收线程(collector)和用户线程(mutator)可并发执行,允许多个回收线程并行。

类型精确(type accurate),非代龄(non-generational),非收缩(non-compacting)。

使用写屏障(write barrier)实现并发标记(mark)和清理(sweep)。

相对于专门处理垃圾回收的 collector 线程,其他线程被称作 mutator 线程。

包含以下几个步骤:

1. 确保清理结束。

a. STOP-THE-WORLD,让所有 P 到达回收安全点。

b. 清理所有未及清理的内存块(span)。

比如在正常清理未结束前执行 runtime.GC,就会出现这种情况。

2. 开始标记。

a. 状态 GCoff -> GCmark,启用写屏障,启用用户辅助(mutator assists),

根标记任务排队。在所有 P 写屏障启用前,不会扫描任何对象,这需要启用 STW。

b. START-THE-WORLD。即刻起,回收任务由调度器(scheduler)启动的

标记工人(mark workers)和分配辅助(assists)完成。

任何指针写入(overwritten pointer and the new pointer),都被写屏障遮蔽。

新分配对象直接标记为黑色。

在垃圾回收期间,用户线程的内存分配行为受信用量限制。

如超出,则需要暂停用户逻辑,参与辅助垃圾回收工作。

以此抑制过快的分配行为导致回收周期无法结束等问题。

c. 执行根标记任务。包括扫描所有栈(stacks),对全局变量和

堆外(off-heap runtime)数据结构里的堆指针着色。

扫描栈会导致 goroutine 停止,着色(shades)其中发现的指针,

随后恢复 goroutine 执行。

d. 清空(drain)灰色队列(queue of grey objects),扫描其中的灰色对象,

将其标记为黑色。同时,对其包含的指针进行着色,将引用目标放入灰色队列。

e. 使用分布式终止算法(distributed termination algorithm)检测何时不再有

根标记任务和灰色对象(gcMarkDone)。

至此,转入标记结束。

3. 标记结束。

a. STOP-THE-WORLD.

b. 状态 GCmarktermination,禁用标记工人和分配辅助。

c. 处理内部任务(flushing mcaches)。

4. 执行清理。

a. 状态 GCoff,设置清理状态,禁用写屏障。

b. START-THE-WORLD。从此刻起,新分配对象为白色,必要时会在

分配前清理目标 span 内存。

c. 后台并发执行清理,并响应分配操作。

当分配超过一定阈值,重新从 1 开始执行新的回收周期。

concurrent sweep

清理与用户逻辑并发执行。使用专门 goroutine 在后台一个接一个清理(span)。

标记结束后,所有 span 都被标记为需要清理(needs sweeping)。

为避免向 OS 请求过多内存,首先尝试清理现有的 span 以获取可复用空间。

确保不会在未清理的 span 上执行操作,避免破坏标记位图。

回收期间,mcache 持有的 span 全部收回 mcentral。重新获取时,会执行清理操作。

当下一回收周期启动时,会先完成未清理任务。

oblets

为防止扫描大对象耗时过长,同时改善并行性,将大于 maxObletBytes 的对象扫描作业

分成多个(maxObletBytes)。

如此,扫描大对象时,先处理第一个 oblet,其他的排队成为新任务。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文