婴儿的第二个垃圾收集器

这是一篇关于复制垃圾收集器的博客文章,主要内容如下:

  • 背景与来源:基于经典博客文章,对比复制收集器与普通收集器的性能和实现,代码可在Github 仓库获取。
  • 复制收集器介绍:与后备分配系统紧密结合,有两个逻辑(物理)内存区域,活动区域用于分配新内存,垃圾收集时交换区域,收集活对象并将其从非活动区域迁移到活动区域,移动对象后可重用非活动区域的对象来保存对象图拓扑和修复引用循环。
  • Cheney 算法:具体算法为Cheney's Algorithm,包括交换活动堆、遍历根集并迁移指针、处理新分配对象等步骤,用伪代码表示为collect_garbage()函数。通过图片详细展示了 Cheney 算法的执行过程,包括处理根集、迁移对象等。
  • 世界最小分配器:复制收集器依赖分配器释放内存,不能使用标准库的malloc()free()函数,而使用 bump 分配器,它是一个大的连续内存区域和一个偏移量,每次分配内存返回偏移量处的指针,偏移量增加。clear()操作可重置分配器,将偏移量设置为 0,释放所有分配的内存。
  • 代码修改

    • 修复统一对象模型:更新 VM 的对象模型,删除侵入式链表指针,添加转发指针的情况,更新 VM 模型以存储堆工作列表的开始和结束代码,添加表示对象已转发的新标签。
    • 两个世界最小分配器:需要两个 bump 分配器,一个用于分配,一个用于交换堆时重置偏移量,实现了newHeap()heapAlloc()swapHeap()newObject()等函数来管理分配器和堆。
    • 不再标记,只转发:处理根集,遍历根并对指向的对象进行疏散和转发,当转发对象时,检查是否已转发,未转发则在新堆中分配并复制对象,设置转发指针。
    • 处理间接可遍历对象:遍历新堆中的对象,处理指向旧堆的字段,移动对象并更新指针,直到遍历完整个新堆。
    • 整合垃圾收集:修改gc()函数,调用新的标记和压缩方案,包括交换堆、处理根集、处理工作列表等步骤。
  • 复制收集器的优缺点

    • 优点:去除了额外的指针开销,减少了缓存一致性问题,活动工作取决于活对象数量,减少了碎片化。
    • 缺点:有效可用空间减半,丢失未使用内存,指针到对象不稳定,需要修补根对象,语言 API 会更复杂。
  • 总结:复制收集器是一个简单的项目,在生产中可能会遇到瓶颈和问题,但也不是无用的玩具,曾是前沿研究,现在仍有在生产中使用的版本,如 Android 运行时。文章还详细描述了复制垃圾收集器的技术细节和实现过程。
阅读 18
0 条评论