继续深入垃圾回收内部机制——generation(代)

        前文再续,书接上一回。昨天我们简要地阐述了垃圾回收理论,虽然很多朋友可能还是感觉雾里看花(还有因为昨天没有时间画图片),但是多少也应该有一个概念了吧?(否则我就白写了,呵呵)那么今天我们将会继续深入垃圾回收内部机制——generation(代)

        正如我们昨天所说的,“代”用来对托管堆进行分区。托管堆是一个存储区域,公共语言运行库(CLR)应用程序所有的内存分配都是在这里进行的。图1显示了托管堆和三个代带。下面将简短说明这张图的意思。

 

        在.NET应用程序的整个运行过程中,会发生两种类型的垃圾回收:完全回收和部分回收。完全回收会停止应用程序的执行,进而扫描整个托管堆来查找根。根可以有多种情况,大部分时候根主要是堆栈变量以及包含对托管堆引用的全局对象,例如在程序中有全局作用于的类对象。在完全回收过程中,回收器将遍历所有根,并标记每一个可以到达的,即每一个活跃的对象。当回收期回收完成后,将会保存可打倒的对象的列表,而不可到达的对象会被宣告死亡,并会有垃圾回收器丢弃。回收的最后过程中有一部分涉及了对托管堆的压缩和碎片整理。

        由于完全回收对应用程序的性能有巨大的影响,在完全回收完成之前,应用程序会停止响应,因此需要一些更快的途径来减轻对应用程序的影响。这样就产生了部分回收。部分回收中用到了带(参见图1)的概念。越是最近分配的对象,其代的级别就越低。因此,可以认为Generation 0(代0),通常也称Gen 0或者 G0中包含最新分配的对象。

        在进行部分回收是,与完全回收一样,都挥锨遍历根。但是会忽略老的对象,即Gen1或者Gen2中的对象,而今对Gen0种得跟进行检查和回收。这里假设所有的老对象仍然是活跃的,因此拖迟了完全回收的进行。M$通过对程序的研究分析,断定程序最大的搅拌(即快速分配和解除分配)往往发生在短期对象中,如临时变量、临时字符串、占位符以及小的工具类。简单的说,回收最频繁的是代0的对象,并且回收代0的对象耗时也是最少。


        前述工作方式建立在老的对象仍然是活跃着的基础上。如果要精确判断何时对代1或者2进行回收,那么就需要了解这些高级别代中的对象何时被修改。这种“脏”标志的储存是通过名位牌桌(Card Table)的数据结构来实现的。牌桌就是一个位数组,每一个位代表一个特定的内存段。在不同操作系统中,根据垃圾回收其实现方式的不同,每一位件事的内存大小也不同,当写入对象处在受牌桌件事的内存段中时,位标志转换,标示着一块内存被修改。

        GC中世纪的部分回收于之前讨论的一样,但是有一点变化。当G0回收发生后,所有修改过的老对象(根据牌桌指示)将作为根来处理。然后会将这些根作为G0的根进行遍历,并且在执行一次回收。

 

        好了,今天就到这里。将来我们将会陆续讨论“垃圾回收期的代码编写”和“非确定性终结与析构”、“CLR中内存与类的管理”等问题。敬请大家继续关注啦!不过看了要回复哦,否则就没有动力继续写了。呵呵

posted @ 2006-08-04 17:31  随风而逝  阅读(257)  评论(0编辑  收藏  举报