GC增量算法的理论与实践

本文深入探讨了GC增量算法,包括它的理论基础、三元色标记机制和在MMgc中的具体实现。通过分阶段进行垃圾收集,减少应用程序中断,以适应实时系统的需求。MMgc在内存分配达到一定比例时启动收集,并使用写屏障来处理白色对象的写入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  author:tuiye@126.com
MMgc 为例
 
垃圾收集
       垃圾收集(Garbage Collection,GC)是一种自动打扫和清除内存垃圾的技术,它可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽,以及不恰当的内存释放所造成的内存非法引用。计算机语言中,很多利用了这一技术来自动管理与之相关联的内存的清除,如Java,Perl,Python,Ruby,JavaScript等。但各自的机制不尽相同,例如Java是比较复杂的自适应GC技术,囊括Mark-Sweep,增量算法(Incremental Algorithm)等;Perl为引用计数(Count Reference);Python采用分代机制(Generation Algorithm);Ruby是标记清除(Mark-Sweep);JavaScript的不同引擎采用的迥异,Spider monkey是标记清除(Mark-Sweep),而Tamarin是又在此之上增加了增量算法。
 
         以上基本囊括了比较流行的GC算法,除此之外还有复制(Copying)算法与标记整理(Mark-Compact)算法等。这些算法各自有自身的优势,有的实现简单,有的回收及时(也可说内存峰值可以保持在较低水准),还有些可以用于实时系统(即每次收集不会占用很大CPU时间,造成停顿感),因此对于不同需求有应采用不同的方式。譬如一个需要 进行实时垃圾收集的运行环境采用增量收集是一个比较好的选择。
 
增量算法理论与三元色机制
         增量收集算法的基础仍是传统的标记清除和复制算法。增量收集算法通过对进程间冲突的妥善处理,允许垃圾收集进程以分阶段的方式完成标记、清理或复制工作。增量算法的具体机制可以用不同,但其思想都是把堆栈分为多个域,每次仅从一个域收集垃圾,从而造成较小的应用程序中断,其中比较著名的是火车(Train)机制与三色(三元色,Tri-Color)标记机制。以下介绍一下三元色机制的概念。
 
         在垃圾收集中,所有的对象可能出于其下的三种颜色中的一种:黑色,灰色与白色。各自代表:
         黑色(black):表示此节点已被访问到,且是live的(其子节点也被访问到),不会被回收(reclaimed);
         灰色(gray):表示此节点已在处理列表中,但其子节点尚未被检查;
         白色(white):表示此节点没有访问过,在GC完成后被视为垃圾对象;
 
         在标记之前先将堆中所有的分配单元置成白色,然后按深度优先算法遍历每一个单元。当垃圾收集器遍历一个分支的时候,如果一个分配单元及与之相关联的单元都被遍历到,则将其标记成黑色。如果一个单元被遍历到,但是与之相关联的单元尚未被遍历,则将该单元标记成灰色。这时,垃圾收集器将继续遍历与该灰色单元相关联的单元,直到这些相关联的单元全部被遍历到,才能将这个灰色单元标记成黑色。最后当所有被遍历到的单元都被标记成黑色的时候, 将堆中被标记成白色的分配单元回收。
 
         收集器处理过程中,去检测节点是否是能到达的(reachable),此活动中依靠找到从灰色节点到白色节点的边缘与把白色节点染色成灰色。因此每步跟踪包含选择一个灰色节点并且把其白色子节点标记成灰色。
[1] 灰色节点只有可能连接到另外的灰色的节点或黑色的节点,那么把它标记为黑色;
[2] 当没有灰色的节点剩下的时候,所有可到达的部分都已找到,余下的白色的节点都被回收。
         注意,黑色节点不可能有白色的子节点!也就是说黑色节点不能指向白的节点,这一点叫做不变量(invariant)。
 
为了保护与防止此种情况的发生,引入了读屏障(Read Barrier)与写屏障(Write Barrier)。
读屏障:当mutator存储一个从黑色转到白色的节点时引用,把其父或子节点置成灰色;(Detects an attempt to read a white object and immediately colors it gray)
x.f = y;     ->     black2gray(x).f = y;
写屏障:当mutator请求一个白色节点时,把它置成灰色;(Traps attempts to write a pointer into an object)
x.f = y;     ->     x.f = white2gray(y);
 
一个实现 MMgc
         在以上网址中,对Tamarin中实现的MMgc做了一个比较全面的阐述。当然在MMgc中不仅仅用了增量技术,但这里我们着重对增量技术做说明。
         [1] 所有在GC中的根 s (roots)被压入队列(queue),此时所有根 s 为gray,而除此之外的都为white;
         [2] 在队列(queue)处理过程中,所有live objects有2种可能变化,从gray到black,从white到gray;
         [3] 当一个指向white对象的指针写入一个black对象的时候,此时不得不中断其写入行为,把white放入队列(queue),(注:这就是写屏障);当然此时还有另一种办法,就是把black对象放入队列,此种方式好处是当很多white对象写入同一个black对象是,我们只需要压入一次black对象,这样特别是当black对象是一个很大的数组的时候,对效率提高是比较有用的。另一方面,如果black对象的数组很大,而写入此对象的新的white对象很少,那么mark一个很大的black对象也是很低效的事件;
 
         所以引入一个比较流行的解决方案,叫做卡片标记( card marking ),不过 MMgc 未作实现( MMgc 作的是把 black 对象移到 gray ,即压入 queue ),其理论如下:(略, MMgc 未作实现)
 
         增量收集的时间片
         当前MMgc中,决定何时收集(collect)行为的是基于多少内存已被分配出来了,如果现在分配出来的内存占heap内存的一定比例以上的时候,MMgc会做收集(collection)。相似地,标记(mark)也可以基于以上的方式,当ISD(incremental start divisor)为4时候,那么只有heap的内存余下1/4的时候,就开始标记;当ISD为1的时候,意味着标记是经常要做的。
 
         决定时间片的因素有2个:
[1] the rate at which we can trace memory
[2] the rate at which the mutator is requesting more memory

参考文献
[1] GARBAGE.COLLECTION.Section6.pdf
[2] Wirth.ppt
[3] Incremental Tracing Collectors.pdf
[4] thesis-newgc.pdf
[5] garbagecollection.pdf
[6] orp.pdf
[7] Scheduling.Garbage.Collection.in.Embedded.System.pdf
[8] hirzel-dissertation.pdf
[9] color.pdf
[10] ASM.ppt
[11] 垃圾收集趣史
[12] 垃圾回收器基础与性能提示(card marking)
[13 ] Uniprocessor Garbage Collection Technique.ppt (tri-color)
[14] Incremental Mature Garbage Collection Using the Train Algorithm.htm (card marking)
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值