JVM之Garbage Collector对比

393 阅读4分钟

Abstract

JVM中有众多的垃圾收集器,每一种使用的技术或者引用场景均不相同,这篇文章简述一下常用的GC。

  • PSGC
  • G1
  • Shenandoah

\color{red}{TODO}

  • ZGC
  • CMS

Introduction

Technology

Overview of GC

##

在可达性分析的GC过程中,可以大致分为两个过程:Mark(标记)阶段,Sweep/Compact/Copy阶段。(对于使用Compact/Copy方式回收堆的GC,最终还需要更新所有的reference,通常分为两步:更新所有root自身reference,由root节点更新其引用对象,递归的更新. Note:\color{red}{个人看法})

Shenandoah

Prallel Scavenge

G1

G1是一款响应时间优先的Region-based垃圾回收器,G1允许设置通过MaxGCPauseMillis参数给JVM的GC过程占用时间设置一个软限制(该限制不确保一定能达到),通过使用启发式算法,利用以往的region回收数据,计算需要回收的old region数量,来达到软限制的目的。## G1在第JDK9中已经替换CMS成为JDK的默认GCJEP 248

存在垃圾收集器通过使GC过程能中断,来实现硬时间限制。

在分代模型的JVM中,存在两种GC:Minor GC以及Full GC,G1的一个目的就是为了减少Full GC。 Minor GC在所有GC中都会STW,但因为需要处理的数据量小,时间短,虽然执行频繁,但总停顿时间仍然能接受。## Full GC在JVM中可能会出现长停顿,或者占用大量的CPU资源,虽然相对出现次数较少,仍然是一个对系统有很大影响。 G1通过提供一种新的GC策略:Mixed GC,将部分old generation的数据在Mixed GC中回收,减少Full GC的次数。

Minor GC

G1的Minor GC使用copy算法(cheery算法迭代复制),在此过程中STW,GC过后会动态调整young region的大小(使用空闲region列表扩展##)

类似于ParNew##.

Minor GC过程

  • STW
  • CSet = young regions
  • Parallel Tasks
    • 扫描所有根对象,并复制到Survivor区域(所有CSet都会被回收,所以CSet的RemSet不需要更新)
    • 处理所有CSet之外的region到CSet的引用:将该部分视为root
      1. 复制obj到新的Survivor区域,对于obj引用的对象,若obj.field 在CSet中,则深度优先,将该obj.file加入处理队列中,若obj.field不在Cset中,则更新其RemSet.
  • 其他任务:处理GC使用的空间,内存扩展,决定是否进行Mixed GC等步骤.

Note: 不使用 Card Table进行代际引用搜索。

Mixed GC

和Minor GC以及Major GC(Full GC)相比,Mixed GC将会收集全部young region以及部分old region.## Mixed GC可以分为两个大部分:Concurrent Mark 以及 Parallel Compact两个过程。 和Minor GC相比,Mixed GC使用STAB(Snapshot At the Beginning)以支持Concurrent Mark。

因此和PSGC相比,在G1中一共使用了两个write barrier,一个处理RemSet,一个处理GC过程中的STAB.

Mixed GC过程

* : Mark阶段, ** : 清理阶段

  • (Initial Mark)初始标记(STW)* Mixed GC只会在YGC之后运行,会用YGC保存在Survivor的结果作为根,不在需要一轮单独的Initial Mark.
  • (Root Region Scanning) 扫描,因为借用了YGC的结果,这一阶段必须在YGC发生之前。
  • (Concurrent Mark)并发标记* 使用STAB,Remember Set和Write Barrier实现并发标记,这一阶段在达到 InitiatingHeapOccupancyPercent阈值之后启动,此过程中会记录每个Region的相关信息,用于Compact整理阶段
  • (Remark)再标记(STW)* 这个阶段可以Parallel,目的是为了结束标记过程。因为Concurrent Mark过程可能一直有STAB处理,在这里处理完所有的引用变更。 ParallelGCThreads可以设置该过程使用的线程数目。
  • (Clean Up)清理阶段*
  • Compact **

Full GC

G1的Full GC使用mark-sweep-compact算法实现,在JEP 307中由单线程改为了Parallel。

Shenandoah

Shenandoah是一款面向大堆的低延迟Region-based垃圾收集器,最初由Red-Hat开发。 Shenandoah的几个特点:

  • 1)相比G1,并发回收,做到了尽可能的并发,延迟大大降低(当然,牺牲了一点吞吐量)。
  • 相比G1,不提供分代的region.
  • 不使用Remember Set记录region之间引用关系,使用邻接矩阵?是吗?##
  • 为了实现1),使用Brooks forward指针,因此
    • 1)添加了一个read barrier(性能有损失);
    • 2)修改了object layout:添加forward头
    • 3)GC并发copy过程中实现了一个write barrier来保证 两个object的一致性(论文中花费时间只有:100+ms/2h)
  • 更新引用关系需要再次扫描堆,因此留到下一次GC过程中。

Compare GC

\color{red}{TODO}
  • STAB
  • Barrier
  • [ ]

Reference

  • VEE'20 Deconstructing the Garbage-First Collector
  • Garbage First Garbage Collection
  • Shenandoah: An open-source concurrent compacting garbage collector for OpenJDK