[翻译]G1垃圾收集器(三) 之 G1垃圾收集器

G1 GC

垃圾优先收集器(G1 GC) 是一个服务器型的垃圾收集器,它的目标是大内存,多处理器的机器。高概率的满足一个垃圾回收暂停时间的目标下,实现大吞吐量。(译者注:例如设置的垃圾回收暂停时间是200ms,G1可以保证90%的垃圾回收暂停时间都在200ms以内,从而保证大的吞吐量),在jdk1.7update4 及其以后的版本完全支持G1 GC,G1 GC主要是为下面这样的应用设计的:

    • 就像CMS收集器一样,可以和应用线程并行处理
    • 紧凑的空间,不会因为GC导致长时间的暂停
    • GC的暂停时间,希望更多的是可以预见的(译者注:意思就是说,大部分GC时间都是可以控制的,因为G1可以保证90%的GC都在目标时间以内)
    • 不想牺牲大吞吐量的性能
    • 不需要更大的内存

G1 GC的长期计划,就是为了替代CMS GC。比较CMS GC和G1,他们很多不同点表明G1 GC是个更好的解决方案。其中一个不同点就是G1是一种压缩收集器,G1对堆栈的充分压缩,可以避免使用细粒度的未分配内存列表去分配内存,而是使用region的概念。这大大简化了收集器的部分,更大程度上消除了潜在的碎片问题。此外,G1比CMS提供了更多的对收集暂停时间的预测,允许用户设定暂停时间期望目标。

G1操作概述

老的垃圾收集器(像serial,parallel,CMS),全部把堆栈划分成三个区域:年轻代,老年代,以及固定大小的永久代。

老的GC的内存结构图

所有的对象,最终在三个区域中的一个中消亡。

G1 GC采用不同的方式:

G1 GC内存结构

堆被分成一组大小相等的区域,每一块区域对应虚拟机的一片连续内存。他们就像那些老的GC一样,也分成三组(Eden,Survivor,Old)。但是这三种区域没有固定的大小,这在内存使用上提供了更大的灵活性。

G1 GC的执行过程,和CMS有很大类似,G1首先并行进行一个全局的标记,来确认堆内的所有对象的活跃度。在经过标记阶段之后,G1 GC就知道哪些区域大部分都是闲置的。G1 GC首先收集那些可以产生大片空白内存的区域,这就是为什么G1 GC被称为垃圾优先。就像名字一样,G1 GC聚焦它的收集和压缩能力在那些就要被可回收对象(也就是垃圾占满的区域。G1有一个可预测的时间暂停模型,可以让用户指定一个目标,这个模型基于实现这个目标来选择每次收集的区域的个数。

那些有G1确认已到回收时机的区域使用撤离的方式进行回收垃圾。G1从一个或者多个区域中复制对象集中到一个区域中,在复制的过程中进行压缩和释放内存。这个撤离的过程在多处理器中是必行处理的,目的就是减少暂停时间和增大吞吐量。因此每次垃圾收集,G1 GC都要在用户设定的暂停时间内不断的工作,以减少碎片的产生。CMS收集器不会做压缩工作,老的Parallel收集器之做全堆的压缩,这会导致相当大的暂停时间。

有一点要特别注意,G1 GC不是一个实时的收集器,它只是说更大可能的满足你设定的暂停时间,但是也不是一定的。通过前面的收集,G1 GC会大体估算出来在你指定的目标时间内能够收集多少区域。因此G1 GC有一个对收集成本的考量模型,G1 GC通过这个模型来决定哪些,多少区域需要收集来保证这个暂停时间目标。

注意:G1 GC有并发和并行的两种阶段,例如refinement, 标记, 清除阶段,是并发执行,stop-the-word是并行处理的(译者注:并发和并行的概念要研究下)。Full GC仍然是单线程处理的,但是如果你调优的恰当,这种情况是可以避免的。

G1 自占内存

如果你是从老的Parallel GC或者CMS GC转到G1,你会发现更的进程占用,这主要和统计类的数据结构有关,例如Remembered SetsCollection Sets

Remembered Sets简称RSets,跟踪一个区域内对象的引用,在堆内,每一块区域对应一个RSet。RSets能让每个区域的收集都是独立并行的。RSets整体占小于5%的内存。

Collection Sets 简称CSets,是GC中需要收集的区域的集合,在一个GC过程中,CSets中所有的活动的数据都要被挪动(包括移动和复制),CSets可以是Eden, survivor, old任意类型的区域,Csets对jvm的大小(译者注:只要是说内存吧)有小于1%的影响。

推荐使用G1 GC的情形

G1第一个关注点是,为那些需要大内存,低GC时延的应用提供一个解决方案。也就是说内存可以到6G甚至更大,可以保证在0.5秒以下稳定的暂停时间。

使用CMS GC和老Parallel GC的应用程序,在有以下一个或者多个特征的情况,比较适合切换到G1 GC:

  • Full GC时间太长,发生太频繁
  • 内存分配的速率或者晋升的速度显著提高(译者注:意思是GC的效率赶不上内存分配的速度)
  • 长时间的GC和内存压缩(长于0.5秒到1s了)

注意:使用CMS和老的Parallel GC的应用程序,如果没有出现长时间的GC和暂停,保持使用当前的GC也是没问题的,最新的JDK,是不强制转用G1 GC的.

  1. kuff说道:

    All memory objects end up in one of these three sections.

    所有的对象,最终在三个区域中的一个中消亡。

    应该翻译成

    所有对象,最后都会存在于这三个部分的某一个.

回复 取消

提示:你的email不会被公布,欢迎留言^_^

*

验证码 *