小结:
1、GC和程序处理的本质是无关的;
2、增量回收:预测和控制GC所产生的中断时间;
1、
分代回收
GC和程序处理的本质是无关的,因此它所消耗的时间越短越好。分代回收的目的,正是为了在程序
运行期间,将GC所消耗的时间尽量缩短。
基本思路
利用了一般性程序所具备的性质,即大部分对象都会在短时间内成为垃圾,而经过一定时间依然存活的
对象往往拥有较长的寿命。如果寿命长的对象更容易存活下来,寿命短的对象则会被很快废弃,那么到底
怎样做才能让GC变得更加高效呢?
如果对分配不久,诞生时间较短的“年轻”对象进行重点扫描,应该就可以更有效地回收大部分垃圾。
在分代回收中,对象按照生成时间进行分代,刚刚生成不久的年轻对象化为新生代(young generation)
,而存活了较长时间的对象化为老生代(old generation)。根据具体实现方式的不通,可能还会划分更多的代。
只扫描新生代对象的回收操作,被称为小回收(minor GC)。
随着程序的运行,老生代区域中的“死亡”对象也在不断增加。为了避免这些死亡的老生代对象白白占用内存空间,
偶尔需要对包括老生代区域在内的全部区域进行一次扫描回收。像这样以全部区域为对象的GC操作被称为
完全回收(full GC)或者大回收(major GC)。
分代回收通过减少GC中扫描的对象数量,达到缩短GC带来的平均中断时间的效果。
不过由于还是需要进行大回收,因此最大中断时间并没有得到什么改善。
从吞吐量来看,在对象寿命假说能够成立的程序中,由于扫描对象数量的减少,可以达到非常不错的成绩。
但是,其性能会被程序行为、分代数量、大回收触发条件等因素大幅度左右。
2、
增量回收
在机器人的姿势控制程序中,如果因为GC而让控制程序中断了0.1秒,机器人可能摔倒。
或者,如果车辆制动控制程序因为GC而延迟响应的话,后果也是不堪设想的。
在这些对实时性要求很高的程序中,必须能够对GC所产生的中断时间做出预测。例如,可以将
“最多只能中断0.01秒”作为附加条件。
在一般的GC算法中,作出这样的保证是不可能的,因为GC产生的中断时间与对象的数量和状态有关。
因此,为了维持程序的实时性,不等到GC玩不完成,而是将GC操作细分成多个部分逐一执行:增量回收 incremental GC
由于增量回收的过程是分步渐进式的,可以将中断时间控制在一定长度之内。另一方面,由于中断操作需要消耗一定的时间,
GC所消耗的总时间就会相应增加,正所谓有得必有失。
3、
并行回收
并行回收可以可用多CPU的性能,尽可能让这些GC任务并行(同时)进行。