G1 GC 调优学习 了解有关如何调整和调整G1 GC以进行评估,分析和性能的信息。

 G1 GC是Java HotSpot虚拟机的低暂停服务器风格分代垃圾收集器。G1 GC使用并发(concurrent)和并行(parallel)阶段来实现其目标暂停时间并保持良好的吞吐量。当G1 GC确定需要进行垃圾收集时,它将首先收集存活数据最少的区域(垃圾优先处理)。

垃圾收集器(GC)是一种内存管理工具。G1 GC通过以下操作实现自动内存管理:

  • 在年轻一代分配对象,并将老化的对象提升为老一代。
  • 在并发(并行)标记阶段,在老一代中查找存活对象。当Java堆总占用量超过默认阈值时,Java HotSpot VM会触发标记阶段。
  • 通过并行复制,压缩存活对象来恢复可用内存。

在这里,我们研究如何适应和调整G1 GC以进行评估,分析和性能-我们假设对Java垃圾收集有基本的了解。

G1 GC是一个区域化的代垃圾收集器,这意味着Java对象堆(堆)被划分为多个大小相等的区域。启动时,Java虚拟机(JVM)设置区域大小。区域大小可以从1 MB到32 MB不等,具体取决于堆大小。目标是不超过2048个区域。Eden,survivor和老年代是这些地区的逻辑集合,并不相邻。

G1 GC 有一个力求达到的暂停时间目标(软实时)。在年轻代回收期间,G1 GC 会调整年轻代空间(eden 和survivors大小)以满足软实时目标。在混合回收期间,G1 GC 会根据混合垃圾回收的目标次数调整所回收的old区域数量,并调整堆的每个区域中存活对象的百分比,以及总体可接受的堆废物百分比。

G1 GC 将一组或多组区域(称为Collection Set (CSet))中的存活对象以增量、并行的方式复制到不同的一个或者n个新区域来实现压缩,从而减少堆碎片(类似young区的复制算法)。目标是从可回收空间最多的区域开始,尽可能回收更多的堆空间,同时尽可能不超出暂停时间目标(垃圾优先)。

G1 GC 使用独立的记忆集 (Remembered Sets RSet) 跟踪对区域的引用。独立的 RSet 可以并行、独立地回收区域,因为只需要对区域(而不是整个堆)的 RSet 进行区域引用扫描。G1 GC 使用后写屏障记录堆的更改和更新 RSet。

垃圾回收阶段(翻译成 gc准备阶段 比较好吧)

除了构成停顿 (STW) 年轻代和混合垃圾回收的排空操作(evacuation)暂停(如下所述),G1 GC 还具有并行、并发和多阶段标记周期。G1 GC 使用初始快照 (SATB----Snapshot-At-The-Beginning) 算法,在标记周期之初为堆中的存活对象集创建快照。存活对象集包括快照中的存活对象,以及标记周期开始以来所分配的对象。G1 GC 标记算法使用预写屏障记录和标记作为逻辑快照一部分的对象。

young gc(young gc)

G1 GC 可满足来自被添加到 eden 区域集的区域的大多数分配请求。在年轻代垃圾回收期间,G1 GC 会同时回收 eden 区域和上次垃圾回收的survivor区域。Eden 和survivor区的存活对象将被复制或疏散到新的区域集。特定对象的目标区域取决于对象的年龄;足够老的对象疏散到老年代区域(也就晋级);否则疏散到survivor区,并将包含在下一次年轻代或混合垃圾回收的 CSet 中。

mixed gc(full gc,全局gc  mixed gc 新概念,不同于full gc)

成功完成并发标记周期后,G1 GC 从执行young gc切换为执行mixed gc。在mixed gc期间,G1 GC 可以将一些old区域添加到将要被垃圾回收的 eden 和survivor区(翻译一下就是mixed gc会回收一些old区和 young区)。所添加old区域的确切数量由一系列标志控制。关于标志的信息,将在后面讨论(请参见“掌握混合垃圾回收”)。G1 GC 回收了足够的old区域后(经过多次混合垃圾回收),G1 将恢复执行年轻代垃圾回收,直到下一个标记周期完成。

标记周期的各个阶段

标记周期包括以下几个阶段:

  • 初始标记阶段:在此阶段,G1 GC 对根进行标记。该阶段与常规的 (STW) 年轻代垃圾回收密切相关。
  • 根区域扫描阶段:G1 GC 在初始标记的存活区扫描对老年代的引用,并标记被引用的对象。该阶段与应用程序(非 STW)同时运行,并且只有完成该阶段后,才能开始下一次 STW 年轻代垃圾回收。
  • 并发标记阶段:G1 GC 在整个堆中查找可访问的(存活的)对象。该阶段与应用程序同时运行,可以被 STW 年轻代垃圾回收中断。
  • 重新标记阶段:该阶段是 STW 回收,帮助完成标记周期。G1 GC 清空 SATB 缓冲区,跟踪未被访问的存活对象,并执行引用处理。
  • 清理阶段:在这个最后阶段,G1 GC 执行统计和 RSet 净化的 STW 操作。在统计期间,G1 GC 会识别完全空闲的区域和可供进行混合垃圾回收的区域。清理阶段在将空白区域重置并返回到空闲列表时为部分并发。

重要的默认值

G1 GC 是自适应的垃圾回收器,提供了若干默认设置,使其无需修改即可高效地工作。以下是重要选项及其默认值的列表。此列表适用于最新的 Java HotSpot VM build 24。您可以通过在 JVM 命令行输入下列选项和已更改的设置,根据您的应用程序性能需求调整和调优 G1 GC。

  • -XX:G1HeapRegionSize=n

    设置the size of a G1 region的大小。值是 2 的幂,范围是 1 MB 到 32 MB 之间。目标是根据最小的 Java 堆大小划分出约 2048 个区域。

  • -XX:MaxGCPauseMillis=200

    设置最长暂停时间目标值。默认值是 200 毫秒。

  • -XX:G1NewSizePercent=5

    设置年轻代最小值所占总堆的百分比。默认值是堆的 5%。这是一个实验性的标志。有关示例,请参见“如何解锁实验性虚拟机标志”。此设置取代了 -XX:DefaultMinNewGenPercent 设置。Java HotSpot VM build 23 中没有此设置。

  • -XX:G1MaxNewSizePercent=60

    设置年轻代最大值所占总堆的百分比。默认值是 Java 堆的 60%。这是一个实验性的标志。有关示例,请参见“如何解锁实验性虚拟机标志”。此设置取代了 -XX:DefaultMaxNewGenPercent 设置。Java HotSpot VM build 23 中没有此设置。

  • -XX:ParallelGCThreads=n

    设置 STW 工作线程数的值。将 n 的值设置为逻辑处理器的数量。n 的值与逻辑处理器的数量相同,最多为 8。

    如果逻辑处理器不止八个,则将 n 的值设置为逻辑处理器数的 5/8 左右。这适用于大多数情况,除非是较大的 SPARC 系统,其中 n 的值可以是逻辑处理器数的 5/16 左右。

  • -XX:ConcGCThreads=n

    设置并行标记的线程数。将 n 设置为并行垃圾回收线程数 (ParallelGCThreads) 的 1/4 左右。

  • -XX:InitiatingHeapOccupancyPercent=45

    设置触发标记周期的 Java 堆占用率阈值。默认占用率是整个 Java 堆的 45%。

  • -XX:G1MixedGCLiveThresholdPercent=65

    为混合垃圾回收周期中要包括的old区域设置占用率阈值。默认占用率为 65%。这是一个实验性的标志。有关示例,请参见“如何解锁实验性虚拟机标志”。此设置取代了 -XX:G1OldCSetRegionLiveThresholdPercent 设置。Java HotSpot VM build 23 中没有此设置。

  • -XX:G1HeapWastePercent=10

    设置您愿意浪费的堆百分比。如果可回收百分比小于堆废物百分比,Java HotSpot VM 不会启动混合垃圾回收周期。默认值是 10%。Java HotSpot VM build 23 中没有此设置。

  • -XX:G1MixedGCCountTarget=8

    设置标记周期完成后,对存活数据上限为 G1MixedGCLIveThresholdPercent 的old区域执行混合垃圾回收的目标次数。默认值是 8 次混合垃圾回收。混合回收的目标是要控制在此目标次数以内。Java HotSpot VM build 23 中没有此设置。

  • -XX:G1OldCSetRegionThresholdPercent=10

    设置混合垃圾回收期间要回收的最大old区域数。默认值是 Java 堆的 10%。Java HotSpot VM build 23 中没有此设置。

  • -XX:G1ReservePercent=10

    设置作为空闲空间的预留内存百分比,以降低目标空间溢出的风险。默认值是 10%。增加或减少百分比时,请确保对总的 Java 堆调整相同的量。Java HotSpot VM build 23 中没有此设置。

如何解锁实验性虚拟机标志

要更改实验性标志的值,必须先对其解锁。解锁方法是:在命令行中的实验性标志前,显式地设置 -XX:+UnlockExperimentalVMOptions。例如:

> java -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=10 -XX:G1MaxNewSizePercent=75 G1test.jar

建议

评估和微调 G1 GC 时,请记住以下建议:

  • 年轻代大小:避免使用 -Xmn 选项或 -XX:NewRatio 等其他相关选项显式设置年轻代大小。固定年轻代的大小会覆盖暂停时间目标。
  • 暂停时间目标:每当对垃圾回收进行评估或调优时,都会涉及到延迟与吞吐量的权衡。G1 GC 是增量垃圾回收器,暂停统一,同时应用程序线程的开销也更多。G1 GC 的吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间。如果将其与 Java HotSpot VM 的吞吐量回收器相比较,目标则是 99% 的应用程序时间和 1% 的垃圾回收时间。因此,当您评估 G1 GC 的吞吐量时,暂停时间目标不要太严苛。目标太过严苛表示您愿意承受更多的垃圾回收开销,而这会直接影响到吞吐量。当您评估 G1 GC 的延迟时,请设置所需的(软)实时目标,G1 GC 会尽量满足。副作用是,吞吐量可能会受到影响。
  • 掌握混合垃圾回收:当您调优混合垃圾回收时,请尝试以下选项。有关这些选项的信息,请参见“重要的默认值”:
    • -XX:InitiatingHeapOccupancyPercent 用于更改标记阈值。
    • -XX:G1MixedGCLiveThresholdPercent 和 -XX:G1HeapWastePercent 当您想要更改混合垃圾回收决定时。
    • -XX:G1MixedGCCountTarget 和 -XX:G1OldCSetRegionThresholdPercent 当您想要调整旧区域的 CSet 时。

有关溢出和用尽的日志消息

当您在日志中看到目标空间溢出/用尽的消息时,意味着 G1 GC 没有足够的内存,供存活者和/或晋升对象使用。Java 堆不能扩展,因为已达到最大值。示例消息:

924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space exhausted), 0.1957310 secs]

924.897:[GC pause (G1 Evacuation Pause) (mixed) (to-space overflow), 0.1957310 secs]

要缓解此问题,请尝试以下调整:

增加 -XX:G1ReservePercent 选项的值(并相应增加总的堆大小),为“目标空间”增加预留内存量。

通过减少 -XX:InitiatingHeapOccupancyPercent 提前启动标记周期。

您也可以通过增加 -XX:ConcGCThreads 选项的值来增加并行标记线程的数目。

有关这些选项的描述,请参见“重要的默认值”。

巨型对象和巨型分配

对于 G1 GC,任何超过区域一半大小的对象都被视为“巨型对象”。此类对象直接被分配到老年代中的“巨型区域”。这些巨型区域是一个连续的区域集(n个地址连续的region,为的是可以拿出来连续的地址给大对象分配空间)。StartsHumongous 标记该连续集的开始,ContinuesHumongous 标记它的延续。

在分配任何巨型区域之前,会检查标记阈值,如有必要,还会启动一个并发周期。

在清理阶段或完整的垃圾回收周期内,标记周期结束时会清理死亡的巨型对象。

为了减少复制开销,巨型对象未包括在疏散暂停中(young gc中为了减少暂停,等mixed gc的时候再操作H区)。完整的垃圾回收周期会对巨型对象进行压缩。

由于每个 StartsHumongous 和 ContinuesHumongous 区域集只包含一个巨型对象,所以没有使用巨型对象的终点与上个区域的终点之间的空间(即巨型对象所跨的空间)。如果对象只是略大于堆区域大小的倍数,则此类未使用的空间可能会导致堆碎片化。

如果巨型分配导致连续的并发周期,并且此类分配导致老年代碎片化,请增加 -XX:G1HeapRegionSize,这样一来,之前的巨型对象就不再是巨型对象了,而是采用常规的分配路径。

总结

G1 GC 是区域化、并行-并发、增量式垃圾回收器,相比其他 HotSpot 垃圾回收器,可提供更多可预测的暂停。增量的特性使 G1 GC 适用于更大的堆,在最坏的情况下仍能提供不错的响应。G1 GC 的自适应特性使 JVM 命令行只需要软实时暂停时间目标的最大值以及 Java 堆大小的最大值和最小值,即可开始工作。

Garbage First Garbage Collector Tuning

弄个图,可视化一下Java heap区究竟怎么在那分配的

©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值