开始熟悉G1垃圾收集器

性能基础知识

通常,在调优Java程序时,重点放在两个主要目标之一:响应性或吞吐量。

响应性

响应性是指应用程序或系统响应所请求的数据的速度。

比如:

  • 桌面UI 对一个event事件响应有多快。
  • 一个网站返回一个页面的速度有多快
  • 返回数据库查询的速度有多快

对于注重响应的应用程序,长时间的暂停是不可接受的。重点是在短时间内做出反应。

吞吐量

吞吐量主要关注应用程序在特定时间内工作量的最大化。比如下面测量吞吐量的例子:

  • 在给定的时间内完成的事务数
  • 批处理程序在一个小时内完成的作业数
  • 一个小时内完成的数据库查询数量

对于注重吞吐量的应用程序来说,高暂停时间是可以接受的。因为高吞吐量的应用程序关注一段时间内吞吐量基准测试,快速响应时间不是一个考虑因素。

G1垃圾收集器

Garbage-First(G1)收集器是一款针对服务器端的垃圾收集器,针对具有大内存的多处理器机器。它以较高的概率满足垃圾收集(GC)暂停时间目标,同时实现了高吞吐量。G1垃圾收集器在Oracle JDK 7更新4及以后的版本中得到了完全支持。G1收集器设计用于以下应用:

  • 可以与应用程序线程并发操作,比如CMS收集器
  • 压缩可分配空间,不需要长时间的GC导致的暂停时间
  • 需要更多的可预测的GC暂停时间
  • 不想要牺牲大量的吞吐量性能
  • 不需要更大的Java堆

G1 作为并发标记-清除处理器的长期替代品。与CMS相比,G1有一些不同之处使得G1成为更好的解决方案。一个区别就是G1是一个压缩型收集器。G1充分压缩完全避免细粒度的空闲列表来分配,而是依赖区域(Region)。这大大简化了收集器的部分工作,并在很大成都上消除了潜在的碎片问题。此外,G1提供了比CMS收集器更可预测的垃圾收集暂停,并允许用户指定所需的暂停目标。(One difference is that G1 is a compacting collector. G1 compacts sufficiently to completely avoid the use of fine-grained free lists for allocation, and instead relies on regions. This considerably simplifies parts of the collector, and mostly eliminates potential fragmentation issues. Also, G1 offers more predictable garbage collection pauses than the CMS collector, and allows users to specify desired pause targets.)

G1操作概述

较老的垃圾收集器(并行、串行、CMS)将堆结构分为三个部分:年轻代、年老代和固定内存大小的永久代。

(永久代 jdk1.8之后就变成MetaSpace 了)

所有内存对象最终都在这三个部分中的一个区域里。

G1收集器采用了不同的方法:

整块堆被划分为一组大小相等的小块堆区域,每一个都是连续的虚拟内存。某些区域被设置充当与较老收集器相同的角色(Eden、survivor、old),但它们没有固定的大小。这在内存使用方面提供了更大的灵活性。

当执行垃圾收集时,G1的操作在某种个方面类似于CMS收集器。G1会执行一个并发的全局标记阶段来确定整个堆中活着的的对象。在标记阶段完成后,G1就会知道哪些区域大部分是空的。它首先在这些区域收集,这通常会产生大量的空闲空间。这就是为什么这种垃圾收集方法被称为Garbage-First.顾名思义,G1将其收集和压缩活动集中在堆中可能充满可回收对象(垃圾)的区域。G1使用暂停预测模型来满足用户自定义的暂停时间目标。

被G1认定为成熟可回收的区域通过疏散(evacuation)被垃圾回收。G1将对象从堆中的一个或多个区域复制到堆中的单个区域,在这个过程中压缩和释放内存。这种疏散在多处理器上并行执行,以减少暂停时间并提高吞吐量。因此,随着每次的垃圾收集,G1不断的工作以减少碎片,在用户定义的暂停时间内工作。这超出了之前两种垃圾回收方法的能力。CMS(并发标记清除)垃圾收集器不做压缩。ParallelOld 垃圾收集只执行整个堆压缩,这会导致相当长的暂停时间。

值得注意的是G1不是一个实时收集器。它以较高的概率满足设定的暂停时间目标,但不是绝对确定的。基于之前回收的数据,G1会估计在用户指定的目标时间内可以收集多少个区域。因此收集器对收集区域的成本有一个相当准确的模型,并且它使用这个模型来确定在保持暂停时间目标的情况下收集哪些和多少个区域。

注意:G1有并发(与应用程序线程一起运行,例如细化、标记、清理)和并行(多线程,例如,停止世界)两个阶段。完整的垃圾收集(Full GC)仍然是单线程的,但是如果调整得当,应用程序应该避免完整的GC。

G1推荐用例

G1 的首先关注的是为运行需要大堆且GC延迟有限的应用程序的用户提供解决方案。

这意味着堆大小约为6GB或者更大并且稳定且可预测的暂停时间低于0.5秒。

今天运行CMS或ParallelOldGC垃圾收集器的应用程序,如果具有以下一个或多个特征,则切换到G1将受益。

  • Full GC持续时间太长或太频繁
  • 对象的分配率或者提升率差异很大
  • 不满足于长时间的垃圾收集或者压缩暂停时间(超过0.5到1秒)

注意:如果您正在使用CMS或者ParallelOldGC,并且您的应用程序没有遇到过长时间的垃圾收集暂停,那么可以使用当前的收集器。使用最新的JDK并不需要更改到G1收集器。

回顾分代GC和CMS

并发标记清除(CMS)收集器(也称为并发低暂停收集器)收集老年代。它试图通过与应用程序线程并发执行大部分垃圾收集工作来最小化垃圾收集导致的暂停时间。

通常,并发低暂停收集器不会复制或压缩存活对象。垃圾收集在不移动存活对象的情况下完成。如果内存碎片成为问题,则分配更大的堆。

CMS收集器在年轻代上使用与并行收集器相同的算法。

CMS收集阶段

CMS收集器在堆的老年代上执行以下阶段:

阶段描述
(1)初始标记(暂停世界事件)标记老年代中可达对象 包括那些被年轻代引用的对象(跨带引用)。相对于Minor Gc的暂停时间,通常暂停时间较短。
(2)并发标记当Java应用程序执行时,并发地遍历老年代对象图获取可达对象。从已经标记过的对象开始扫描并且逐渐的标记从根可到达的所有对象。mutators 在并发阶段2、3和5中执行,在这些阶段在CMS 发生中分配的对象(包括晋升对象)都会被立即标记为存活对象。
(3)重新标记(停止世界事件)在并发收集器完成扫描对象之后,查找由于Java应用程序线程对对象的更新而在并发标记阶段错过的对象。
(4)并发清除收集标记阶段中被标识为不可达的对象。死亡对象的集合将对象空间添加到一个空闲列表中,以便以后分配。此时可以合并死对象,注意存活的对象不会被移动。
(5)重置通过清除数据结构为下一次并发收集做准备。

回顾垃圾收集步骤

接下来,让我们一步一步地回顾CMS收集器的操作。

1.CMS收集器的堆结构

堆被分成三个区域。

年轻代被分成Eden区和两个survivor区,而老年代是一块连续的区域。除非发生Full GC,否则不会进行压缩。

2.Young GC 在CMS下是如何工作的

年轻代对象用浅绿色标记,年老代用蓝色标记。如果您的应用程序已经运行了一段时间,那么这就是CMS的样子。对象分散在老年代区域。

使用CMS,老年代对象在适当的位置(什么是适当的位置我也不太清除我觉着就是分配的位置)被回收。它们不会移动。除非发生Full GC,否则空间不会被压缩。

3.年轻代集合

存活的对象从Eden区和一个survivor区复制到另一个survivor区。任何已经达到老化阈值的较老对象被提升到老年代。

4.Young GC 之后

在一次Young GC之后,Eden空间被清理,其中一个Survivor空间被清理。

新晋升的对象在图表中以深蓝色显示。绿色对象是尚存活的年轻代对象,还没有提升到老年代。

5.CMS老年代收集

两个STW事件会发生:初始标记和再次标记。当老年代达到一定的占用率的时候,CMS就启动了。

(1)初始标记是一个短暂的暂停阶段。在此阶段 标记存活(可达)对象。(2)并发标记在应用程序继续执行时查找存活对象。最后,在(3)再次标记阶段,发现(2)并行标记前一阶段中遗漏的对象。

6.老年代收集-并发清除

在前一阶段中未被标记的对象的位置将被重新分配,这时并没还有压缩空间。

Note: Unmarked objects == Dead Objects

7. 老年代收集-清除之后

在(4)sweep 阶段之后,你可以看到大量内存被释放。你还可以注意到没有进行压缩。

最后,CMS收集器将进入(5)重置阶段,并等待下一次达到GC阈值。

G1垃圾收集器

G1收集器采用不同的方法分配堆。下面的图片一步一步地回顾一下G1系统。

1. G1堆结构

G1 下的堆是一个被分割成许多固定大小的区域(region)的内存区域(area)。

region大小由JVM启动时选择。JVM通常以大约2000个大小从1到32MB范围的区域为分割目标。

2.G1 堆分配

实际上,这些区域被映射成Eden、survivor和Old空间的逻辑代表。

图中的颜色显示了哪个region与哪个角色相关联。存活对象被从一个区域疏散(即复制或移动)到另一个区域。

Regions被设计成并行收集或者不停止所有其他应用线程。(Regions are designed to be collected in parallel with or without stopping all other application threads.)-翻译in parallel with or without

如上所示 ,区域可以分配为Eden区、survivor区和generation区域。此外,还有第四种被称为Humongous 区域。这些区域用于保存大小为标准区域的50%或更大的对象。它们被保存在一组相邻的区域中。最后一种区域是堆中未被使用的区域。

注意:在撰写本文时,还没有对收集大型对象进行优化。因此,应该避免创建这种大小的对象。

3.G1年轻代

堆被分成大约2000个区域。最小的大小为1Mb,最大的为32Mb。蓝色区域持有老年代对象,绿色区域持有年轻代对象。

注意:这些区域不需要像旧的垃圾收集器那样是连续的(两个young region 之间不一定连续,可能隔着Old region)。

4.G1年轻代GC

存活对象被疏散(即复制或移动)到一个或多个survivor区域。当满足老化阈值时,部分对象将被提升到Old generation region。

这是一个停止世界的暂停。为了下一次GC Eden大小和survivor大小被计算。在计算大小的时候,像pause time goal 这样的事情也要考虑在内。

这种方法使得调整region大小变得非常容易,可以根据需要放大或缩小区域。

5.一次G1 Young GC 之后

存活对象被疏散到Survivor 区或者 Old 区。

最近晋升对象用深蓝色显示,Survivor Regions in Green.

综上所述,G1的年轻代可以总结为下面说的:

  • 堆是一块被分割成多个区域的内存空间
  • 年轻代内存由一组非连续区域组成。这使得在需要时可以容易的调整年轻代大小。
  • 年轻代的垃圾收集,或年轻的GC,是停止世界事件(STW)。所有应用程序都将为此操作而停止。
  • Young GC 是使用多线程并行完成的。
  • 存活对象是被赋值到新的Survivor区或者Old区 的。

G1的年老代GC

与CMS收集器一样,G1收集器被设计为老年代低暂停收集器。下面描述了老年代G1收集阶段。

G1收集阶段-并发标记周期阶段

G1收集器在堆的老年代上执行以下阶段。注意,有些阶段是年轻代收集的一部分。

PhaseDescription
(1) Initial Mark
(Stop the World Event)
This is a stop the world event. With G1, it is piggybacked on a normal young GC. Mark survivor regions (root regions) which may have references to objects in old generation.
(2) Root Region ScanningScan survivor regions for references into the old generation. This happens while the application continues to run. The phase must be completed before a young GC can occur.
(3) Concurrent MarkingFind live objects over the entire heap. This happens while the application is running. This phase can be interrupted by young generation garbage collections.
(4) Remark
(Stop the World Event)
Completes the marking of live object in the heap. Uses an algorithm called snapshot-at-the-beginning (SATB) which is much faster than what was used in the CMS collector.
(5) Cleanup
(Stop the World Event and Concurrent)
  • Performs accounting on live objects and completely free regions. (Stop the world)
  • Scrubs the Remembered Sets. (Stop the world)
  • Reset the empty regions and return them to the free list. (Concurrent)
(*) Copying
(Stop the World Event)
These are the stop the world pauses to evacuate or copy live objects to new unused regions. This can be done with young generation regions which are logged as [GC pause (young)]. Or both young and old generation regions which are logged as [GC Pause (mixed)].

G1 Old Generation Collection Step by Step

With the phases defined, let's look at how they interact with the old generation in the G1 collector.

6.Initial Marking Phase

Initial marking of live object is piggybacked on a young generation garbage collection. In the logs this is noted as GC pause (young)(inital-mark).

7.Concurrent Marking Phase

If empty regions are found (as denoted by the "X"), they are removed immediately in the Remark phase. Also, "accounting" information that determines liveness is calculated.

8.Remark Phase

Empty regions are removed and reclaimed. Region liveness is now calculated for all regions.

9. Copying/Cleanup Phase

G1 selects the regions with the lowest "liveness", those regions which can be collected the fastest. Then those regions are collected at the same time as a young GC. This is denoted in the logs as [GC pause (mixed)]. So both young and old generations are collected at the same time.

10. After Copying/Cleanup Phase

The regions selected have been collected and compacted into the dark blue region and the dark green region shown in the diagram.

Summary of Old Generation GC

In summary, there are a few key points we can make about the G1 garbage collection on the old generation.

  • Concurrent Marking Phase
    • Liveness information is calculated concurrently while the application is running.
    • This liveness information identifies which regions will be best to reclaim during an evacuation pause.
    • There is no sweeping phase like in CMS.
  • Remark Phase
    • Uses the Snapshot-at-the-Beginning (SATB) algorithm which is much faster then what was used with CMS.
    • Completely empty regions are reclaimed.
  • Copying/Cleanup Phase
    • Young generation and old generation are reclaimed at the same time.
    • Old generation regions are selected based on their liveness.

翻译原文:

Getting Started with the G1 Garbage Collectoricon-default.png?t=M0H8https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/G1GettingStarted/index.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值