垃圾回收机制的算法实现——复制算法
一、复制算法
在上面提到的标记清除算法中,遇到了一个典型的问题,那就是内存碎片的问题。整理内存碎片是一个漫长的不断的搜索的过程。那么有没有一种算法可以解决这个问题呢?这就引出了GC复制算法。这种算法是把整个空间分成From和To相等的两部分,当From部分达到GC阈值时,就将From部分活动内存对象全部复制到To部分。复制完成后,From和To的身份互换。
这个想法有点奇特,不过却挺管用。很明显,这个全拷贝需要一个递归的搜索函数。当然这个问题可以用迭代来搞定。
二、优缺点
GC复制算法的优点:
1、首先就解决了内存碎片问题
把内存都全拷贝走了,还有啥碎片问题,一个新世界都诞生了,哪里还有什么内存的问题。
2、吞吐量高
标记删除算法中,不断标记的过程比较麻烦,不断的遍历,而复制算法就不用,只在GC时搜索一次活动对象,那速度肯定快,吞吐量自然大。特别是内存很大的情况,更有优势。
3、分配效率高
这个是上面一个意思,不需要寻找空闲链表了,直接就开始分配,你说快不快。
4、对缓存的良好性
现代的缓存手段,导致内存在分配上有一定的方式,保障能快速命中,而这种复制算法对其就表现了良好的支持。
GC复制算法的缺点“
1、消耗内存
这种二分法空间,意味着一半的内存永远是空闲状态,也就是现在内存便宜了,要搁以前,估计会被打死。
2、对保守式GC不兼容
这个其实倒不算啥,但多一个朋友多一条出路,所以这也算一个缺点。
三、基本应用
Cheney的GC复制算法算是一个比较好的GC复制算法。而且它不采用递归算法来进行GC,而是采用迭代的方式。递归的缺点,凡是学过算法和数据结构的估计都明白,不容易调试,容易栈溢出等等。同时它也通过堆队列的方式缩小了遍历的代价,不过缺点是,对缓存不再有良好的支持。
GC复制算法一般有以下几步:
1、二分划分内存,指定From和To空间
2、开始GC,复制内存对象从From到To空间
3、复制完成后,修改根指针对象,这个很重要
4、回收From空间内存对象并交换From和To空间
这里面其实有一个小细节需要考虑,在真实的应用场景中,一个对象可能会被多个对象引用,那么在复制时,要考虑不能将它复制多份儿。至于是使用标记还是使用其它方式,就看开发者的想法了。
四、总结
哲学上有辩证统一这个观点,用在GC的算法分析上,其实是相通的。而在实际社会上也是如此,康熙说过:”凡生一事,有一利而必有一弊“。GC算法没有一种能包打天下,一定要弄明白这个道理。做为一名程序员一定要知道,最合适的才是最好的。也正如NP问题,只有最接近的,没有能完全解决的。