本文会简要介绍引用计数标记清除复制算法标记压缩分代垃圾回收

GC算法指标

  • 吞吐量
    指在应用程序的生命周期内,应用程序所花费的时间和系统总运行时间的比值
  • 停顿时间
    指垃圾回收器正在运行时,应用程序的暂停时间
  • 垃圾回收频率
    指垃圾回收器多长时间会运行一次
  • 反应时间
    指当一个对象称为垃圾后,多长时间内,它所占据的内存空间会被释放
  • 堆分配
    不同的垃圾回收器对堆内存的分配方式可能是不同的。一个良好的垃圾收集器应该有一个合理的堆内存区间划分

1.引用计数器(reference counting)

特点

  • 即刻回收垃圾
  • 最大暂停时间短
  • 没有链表查找
  • 额外的计数器空间
  • 频繁的更新计数
  • 实现繁琐
  • 循环引用

2.标记清除(mark-sweep)

分为两个阶段: 标记阶段、清除阶段
标记阶段: 从根出发,遍历对象,并标记(图中打钩的对象)
清除阶段: 清除未标记的对象

特点

  • 实现简单
  • 分配内存时需要遍历链表,较慢
  • 碎片化
  • 与写时复制不兼容

碎片化例子

优化方案一:多个空闲链表

优化分配速度

优化方案二: BiBOP(Big Bag Of Pages)

将大小相近的对象整理成固定大小的块进行管理的做法

优化方案三:位图标记

写实复制兼容。用其他空间标记,对象空间不修改,多进程可共享对象空间。

3.复制算法(GC COPY)

特点

  • 吞吐量比标记-清除高,大堆更明显
  • 高速分配
  • 不会产生碎片
  • 与缓存兼容(有引用关系的对象放在相邻位置)
  • 堆利用率低
  • 递归调用

多空间

堆利用率优化

4.标记压缩(mark-compact)

GC标记-压缩算法(Mark Compact GC)是将 GC 标记-清除算法与GC复制算法相结合的产物

5.分代垃圾回收 (Generational GC)

充分利用各种算法的优点。将不同的数据采用不同的GC算法处理
新生代采用: 复制算法, 速度快
老年代采用: 标记清除算法。堆利用率高

  • 新生代流程

6.Java

gc_java