PHP5.3 的垃圾回收实现原理--同步周期回收机制(未完成版)

来源:互联网 发布:截断数据库是什么意思 编辑:程序博客网 时间:2024/05/16 12:19
转载请注明出处:translated by zhoutao
如有翻译不当的地方,请大家予以指正
同步周期回收在计数统计系统中的应用
抽象的说,自动存储回收通过使用引用计数拥有重要优势,但是同样存在的一个主要问题就是无法重复循环使用数据的结构。
我们描述一个新奇的循环回收算法,它一方面是同步的--尽管同时发生变化,它仍可以回收垃圾;另一方面是本地化--它从不需要去执行一个内部数据空间的全局搜索。
我们详细的描述了我们的算法而且证明了它的正确性。
我们已经在java的虚拟机中应用了我们的算,作为其中一部分的回收算法。一个同步多重处理引用计数垃圾回收,达到最大的突变的停顿时间--仅仅6毫秒。我们提出了 循环回收算法,通过设置8 个标准检查程序,而且论证了同步回收算法在寻找垃圾循环中的影响,处理同步的变化,而且同时消除全局的追踪。
1 介绍
四十年前,有两种自动存储垃圾回收机制被我们所了解:引用计数【7】和追踪【23】,在此之前,追踪回收和他们变异版本(mark-and-sweep, semispace copying, mark-and-compact)已经非常的广泛应用。
存储器和处理能力的相对成本的变化,而且在主流编程中采用垃圾回收语言(尤其氏java)已经改变这种状况。我们相信到了该去重新审视引用计数的时候了,尤其由于处理时钟速度的增长,同时RAM变得丰富起来,而且没有明显的变快。在这种大环境下引用计数的局部性质(the locality properties of)很吸引人,同时跟额外的处理能力变的不非常相关了。
同时,java的垃圾回收的合并已经使这个问题进入到主流当中,而且巨大,关键任务系统已经在java中被建立起来,强调潜在的垃圾回收实施的灵活性和可扩展性。导致的结果,追踪收集器的设想的优势--简单和低消耗--已经被削减,由于她们曾经被设置的更加复杂去记录现实世界中巨大而且不同的程序的需求。


引用计数有三个主要的问题:
1.存储开销与保持每个对象的计数
2.引用计数运行时开销 的增长和减少,时一个被复制的点
3.无法去检测周期,随之而来的需要引用另一个垃圾回收技术去处理循环的垃圾
无法回收循环被视为引用计数回收器最大的缺点。同时给程序员增加了很大的负担去明确的打破循环,或者需要特殊程序语法,或者需要一个追踪回收器去回收循环。
在这里,我们首先展示同步,接下来是在引用计数系统中回收垃圾的结构算法。新的同步算法是同步算法和额外的对主要安全性能的测试的结合体。
像算法基于追踪一样,我们的算法是在图标追踪中是线性的。但是我们的算法可以在本地处理追踪而不是在全局中执行,而且经常追中一个比较小的子图。
这些算法已经使用在新的引用回收计数器中,这个回收器是java vm的一部分,在IBM T.J. Watson Research Center 被执行,Jalapen ̃o 自己将此算法写入到了java中。
在同步出版的书籍中,我们吧回收器描述成了一个整体,同时提供了测量数据显示在我们同步引用计数系统中,达到只有6毫秒的停顿时间测得的最大突变。端到端的执行时间,通常可以比作为并行(但是没有同步)mark-and-sweep 回收器,尽管偶尔有显著的变化(在两个方面)。
在这里我们将重点放在详细的描述循环回收算法。它可以被其他的所执行。同时给出证明正确性的论据,这些论据将会进一步深入的介绍同步回收算法是怎样和为什么这样工作的。我们同时提供循环回收算法的所展现的测量数据量来作为一个整体,(每8个java的基准为一个整套)。
剩余的章节将会讲述一下内容:
第二章 介绍以前的实现方法
第三章 介绍我们同步回收垃圾算法的实现 describes our synchronous algorithm for col- lection of cyclic garbage
第四章 提供我们同步回收垃圾算法
第五章 证明同步循环回收算法的正确性
第六章 展示同步回收算法的效果
第七章 介绍同步垃圾回收相关的资料
最后得出我们的结论。
3.1章节和4.4章节包括详细的算法的伪代码,可以在第一次阅读时掠过这些内容。

2 循环回收的前期准备工作
解决循环回收在引用计数回收问题的前期准备工作已经整理为一下三个分类:
-特殊的编程语法,像Bobrow 的组,或者是某些的方法编程方式
-使用一个很少调用的追踪回收的方法去回收循环的垃圾【8】;
-通过移除内部的引用计数器来搜索垃圾循环

这项技术做的很好的整理和算法在本书的第三章。第一个循环回收算法是Christopher设计的。我们的同步循环回收算法是以Mart ́ınez的研究为基础的,并且被Lins扩展,这部分已经刚刚被非常清晰的在本书的介绍过。
针对这些算法主要有两个基本的观点。第一个观点是垃圾循环只能在当引用计数减少至非0的值时才能被创建。如果引用计数增加,那么不会有垃圾被创建,如果其值减少到0,这部分垃圾就已经被发现。此外,如果引用计数器的值为1时,倾向于主导地位,减少到0 should be common。
第二个观点是在垃圾循环中,所有的引用计数都是内部的;因此,如果这些内部的计数,能被减少,垃圾循环就会被发现。
因此,当一个引用计数值减少,但是不为0时,它会被考虑成为一个垃圾循环的候选人,此时将执行一个本地搜索。这是一个深度优先的搜索,它由于内部指针剪去了计数值(?)。如果一个引用计数值为0,接下来一个垃圾循环会被发现而且会被回收;如果没有的话,另一个深度优先搜索会被执行,而且引用计数会被恢复。
Lins [20]扩展了最初的算法,现在通过缓冲的懒惰搜索代替了立即检测去执行。这有两个优势。第一个是经过一段时间,由于边缘缺失,引用计数的候选人会变成0。在这种情况下,这个节点会被非常简单的回收,或者由于边缘缺失,引用计数会重新增加,在这种情况下它会被忽略为一个候选人。其次,它会通畅禁止再次便利这些节点。
不幸的是,在最坏的情况下Lins 的算法is quadratic in the size of the graph,在循环中作为一个例子展示在图1中。他的算法考虑到在一个时间 root 1执行引用计数减法,并且在那个root采取行动之前恢复通行。
因此,Lins 的算法将会在候选人中执行一个全部扫描,直到它到达最后根,在这个点的时候,整个符合的循环会被收集起来。


3 同步循环回收

在这一章介绍我们的同步循环回收算法,同步循环回收算法应用的原理和Mart ́ınez 、Lins 一样,但是仅仅需要O(N+E) ,对于回收最差的情况时(N 是节点数 ,E是对象图形的边缘数),追踪垃圾回收因此更具有竞争力。

图1.符合循环的例子,引起Lins的算法 ,来展示二次复杂性
我们同时通过允许重新设置回收对象的大小来改进算法的实用性,通过重大的持续的更新可以实现排除固定的非循环的数据结构。?
我们的同步算法和Lins的算法很相似:当引用计数减少的时候,我们将循环垃圾的潜在的根放入到所谓的缓冲区中。我们处理这个缓冲然后通过减去内部的引用计数来寻找循环。
有两个主要改变来实现算法线性时间:首先,我们给每个对象增加了一个缓冲标志,来防止每个循环回收相同的对象被重复添加到根的缓冲中。这反过来线性的约束缓冲区的大小
第二点,我们分析根的内部传递闭包,作为一个单独的图表,而且作为一套图表。这意味着,算法的复杂性受制于传递闭包的大小,反过来受制于(根是通过使用缓存标志来区分的),当然,在实践中,我们希望传递闭包能够有明显的减小。
在实践中,我们发现第一个改变(使用缓存标志)使算法在运行的时候几乎不会有所改变;第二个改变(立即分析内部的图表)在算法运行的时候发生了巨大的变化。当我们应用lins的算法的时候,并且没有重新定义这个巨大的程序,垃圾回收延迟了不到一分钟的时间。
3.1 解释伪代码
我们现在来看下伪代码并且解释同步循环回收算法的每个执行过程。
此外,缓存标志,每个对象豆包括一个颜色和一个引用计数。例如,对象T表示buffered(T), color(T), and RC(T)。在使用的过程汇总,这些特性共同构成了每个对象内的一个单独的文字。
颜色的表示含义:
黑色: 正在使用或者没有被使用
灰色:可能得周期成员
白色:垃圾周期的成员
紫色: 可能的周期的根
绿色: 非循环的
红色: 候选周期
橙色: 候选周期等待被分界

表1.对象颜色的周期回收。 橙色和红色仅仅在同步周期回收中使用,在第四章中将会讲解这部分。
所有的对象开始变黑。在表1中显示了颜色在回收器中的使用。接下来我们来讨论一下绿色的使用(非循环的)。
算法显示在图2中,接下来详细的解释一下他的执行过程。外部的调用增加和减少作为一个指针来增加,移除或者是重写。当根的缓存移除,存储空间被耗用,或者当回收器因为一些其他的原因去释放周期垃圾的时候,回收周期会被调用。剩余的进程是用于内部的周期回收。特别提示,MarkGray, Scan, and ScanBlack 这三个进程是和Lins的算法一样的。

0 0
原创粉丝点击