迈向 Go:Go 垃圾回收器的旅程 - Go 编程语言

这是 Richard L. Hudson(Rick)在 2018 年 6 月 18 日国际内存管理研讨会上的主题演讲记录,主要内容如下:

  • 摘要:Go 语言的特性、目标和用例促使重新思考整个垃圾收集栈,旅程令人振奋,介绍了 Go 语言垃圾收集的发展历程,包括开源和谷歌生产需求的推动,以及在死胡同和正确道路上的探索。
  • 个人简介:Rick 以内存管理工作闻名,目前是谷歌 Go 团队成员,致力于 Go 的垃圾收集和运行时问题。
  • Go 运行时与垃圾收集

    • Go 程序有大量栈,由调度器管理,在垃圾收集安全点被抢占,通过复制栈和更新指针来管理栈大小。
    • Go 是值导向语言,注重内存布局控制和缓存局部性,有指针和提前编译系统,有两个控制垃圾收集的旋钮 GCPercent 和 MaxHeap。
    • 2014 年 Go 面临垃圾收集延迟问题,否则无法成功,其他语言也有类似问题,如 Rust 走了不同道路,Go 选择的路径是解决根本问题。
    • 最初计划做无读屏障的并发复制垃圾收集,但 2014 年短期目标是将运行时和编译器转换为 Go,避免 C 相关的问题,同时要关注延迟且性能损失小于编译器的提升,最终决定做三色并发算法,采用大小隔离跨度、在对象元数据中保留标记位和写屏障等设计。
    • 开发了 GC Pacer 来控制垃圾收集周期,通过反馈循环确定最佳开始时间,平衡标记和分配。
    • 取得了显著的成功,从 2015 年到 2017 年不断降低垃圾收集延迟,达到亚毫秒级,但 2018 年目标是将世界停止暂停时间降低到 500 微秒。
  • 失败尝试

    • 尝试过请求导向收集器(ROC),本地操作无需全局同步,但写屏障昂贵,导致缓存缺失,在一些测试中表现良好但在编译器等方面表现不佳,不是获胜方案。
    • 尝试过非移动的分代垃圾收集,写屏障总是开启,在大型堆上表现不错,但在性能基准测试中表现不佳,写屏障不够快且难以优化,同时逃逸分析使分代收集效果降低。
    • 考虑过无写屏障的卡标记,但在性能基准测试中表现一般,将写屏障从始终开启转移到垃圾收集周期中,可更灵活地控制是否进行分代垃圾收集,但未来硬件发展对其影响未知。
  • 未来展望

    • 使运行时更灵活和健壮,关注调度器以提高确定性和公平性,不增加垃圾收集 API 表面,改进逃逸分析,算法上专注于减少始终开启的屏障的使用,希望利用摩尔定律使内存比 CPU 更有价值。
    • 谷歌 Go 团队正在招聘工程师来开发和维护 Go 运行时和编译器工具链。
阅读 6
0 条评论