1.引用计数算法
每次对对象赋值时均要维护引用计数器,python使用的改算法,算法简单
缺点:
- 计数器本身有一定的消耗
- 较难处理循环引用
- 内存碎片化
2.复制算法
内存分两块区域,将存活对象都复制到另一块区域,然后对非存活区域进行整体回收,适合存活率低的场景
优点:
- 效率高
- 内存整齐度高,不会产生内存碎片
缺点:
- 浪费了一半的内存
- 当存活率非常高时,复制对象和重置引用地址的消耗变大
3.标记算法
程序内存耗尽时,暂停程序,触发GC,由root根部开始递归进行标记'根可达',再对堆进行线性遍历,清除未标记对象
缺点:
- 需要暂停应用程序,用户体验差
- 产生内存碎片化
- 效率低,递归和全堆对象遍历导致
4.标记压缩
标记'根可达'后,不再进行全堆遍历的清除,而是将存活都移动到另一端,形成连续的内存,再对未标记对象区域整体清除
优点:
- 解决了标记清除算法的内存碎片化问题
- 降低了复制算法内存减半的高额代价
缺点:
- 效率低,既要标记,又要整理
分代收集算法
年轻代:
内存空间小,对象存活率低,适合用复制算法,整个年轻代分成三块:一个Eden区两个Suevivor区(from 和 to),比例8:1:1,每次GC将Eden和from里的存活对象放到to,并且年龄+1,对于超龄的直接放进老年代(默认超龄为15),再对Eden和from整体回收,回收完to就成了新的from;
老年代:
内存占用大,对象存活率高,适合标记清除和标记压缩算法混合实现;老年代存活对象多,开销大,会通过并发并行的方式提高效率;