G1收集器调优

G1收集器调优本篇针对官网G1性能调优进行翻译,以此为调优理论依据。本文可作参考模板,在完全理解G1收集器的情况下后续会有更加详细的内容讲解。

大家好,欢迎来到IT知识分享网。G1收集器调优

本篇针对官网G1性能调优进行翻译,并补充部分参数解释。本文可作参考模板亦可为调优理论依据。

另外我整理了一套 G1垃圾收集调优-精简版

目录

G1 的一般建议

从其他收集器转移到 G1

提高 G1 性能

观察Full GC收集

巨大的对象碎片

调整延迟

异常系统或实时使用

引用对象处理时间太长

混合收集耗时太长

高更新 RS 和扫描 RS 次数

调整吞吐量

调整堆大小

可调默认值


G1 的一般建议

一般建议是使用 G1 及其默认设置,最终给它一个不同的暂停时间目标,并根据需要设置最大 Java 堆大小 -Xmx

G1 默认值的平衡与其他收集器不同。G1 在默认配置中的目标既不是最大吞吐量也不是最低延迟,而是在高吞吐量下提供相对较小、统一的暂停。然而,G1 增量回收堆空间的机制和暂停时间控制在应用程序线程和空间回收效率方面都会产生一些开销。

如果您更喜欢高吞吐量,那么通过使用-XX:MaxGCPauseMillis 或提供更大的堆来放松暂停时间目标。如果延迟是主要要求,则修改暂停时间目标。避免使用-Xmn,-XX:NewRatio等选项将年轻代大小限制为特定值,因为年轻代大小是 G1 允许其满足暂停时间的主要手段。将年轻代大小设置为单个值会覆盖并实际上禁用暂停时间控制。

从其他收集器转移到 G1

通常,当从其他收集器(尤其是并发标记清除收集器)移动到 G1 时,首先删除所有影响垃圾收集的选项,并且仅使用-Xmx和 可选设置暂停时间目标和总体堆大小-Xms

许多对其他收集器以某种特定方式响应有用的选项要么根本没有影响,要么甚至降低吞吐量和满足暂停时间目标的可能性。一个例子可能是设置年轻代大小,完全阻止 G1 调整年轻代大小以满足暂停时间目标。

提高 G1 性能

G1 旨在提供良好的整体性能,而无需指定其他选项。但是,在某些情况下,它们的默认启发式方法或默认配置会提供次优结果。本节提供了一些有关在这些情况下诊断和改进的指南。本指南仅描述了 G1 在给定一组应用程序时,在选定指标中提高垃圾收集器性能的可能性。在个案的基础上,应用程序级优化可能比尝试调整 VM 以提高性能更有效,例如,通过完全避免一些寿命较短的对象来避免一些有问题的情况。

出于诊断目的,G1 提供了全面的日志记录。一个好的开始是使用该-Xlog:gc*=debug选项,然后在必要时从该选项中细化输出。该日志提供有关垃圾收集活动暂停期间和之外的详细概述。这包括收集的类型和在暂停的特定阶段花费的时间细分。

以下小节探讨了一些常见的性能问题。

观察Full GC收集

一次全堆垃圾回收(Full GC)通常非常耗时。老年代堆占用过高导致的Full GC可以通过在日志中找到Pause Full (Allocation Failure)字样来检测。Full GC 之前通常是遇到to-space exhausted标记指示的疏散失败的垃圾收集。

发生 Full GC 的原因是应用程序分配了太多无法快速回收的对象。通常并发标记无法及时完成以启动空间回收阶段。由于分配了许多庞大的对象,因此可能会遇到 Full GC。由于这些对象在 G1 中的分配方式,它们可能占用比预期更多的内存。

目标应该是确保并发标记按时完成。这可以通过降低老年代的分配率来实现,或者给并发标记更多的时间来完成。

G1 为您提供了多种选项来更好地处理这种情况:

  • 您可以使用gc+heap=info日志记录来确定 Java 堆上的大型对象占用的区域数量 。Y在“ Humongous regions: X->Y”行中给出了巨大对象占据的区域数量。如果该数字与旧区域的数量相比较高,则最好的选择是尝试减少此对象数量。您可以通过增加区域来实现此目的size 使用 -XX:G1HeapRegionSize选项。当前选择的堆区域大小打印在日志的开头。
  • 增加 Java 堆的大小。这通常会增加标记必须完成的时间量。
  • 通过-XX:ConcGCThreads显式设置增加并发标记线程的数量。
  • 强制 G1 提前开始标记。G1 根据早期的应用程序行为自动确定初始堆占用百分比 (IHOP) 阈值。如果应用程序行为发生变化,这些预测可能是错误的。有两个选项:下,用于当通过增加通过修改自适应IHOP计算中使用的缓冲液启动空间回收所述目标占用-XX:G1ReservePercent; 或者,通过使用-XX:-G1UseAdaptiveIHOP 和手动设置来禁用 IHOP 的自适应计算 -XX:InitiatingHeapOccupancyPercent

除了完整 GC 的分配失败之外的其他原因通常表明应用程序或某些外部工具导致完整堆收集。如果原因是 System.gc(),并且无法修改应用程序源,则可以通过使用 -XX:+ExplicitGCInvokesConcurrent或让 VM 完全忽略它们来减轻 Full GC 的影响-XX:+DisableExplicitGC。外部工具可能仍会强制执行 Full GC;只有不请求它们才能删除它们。

巨大的对象碎片

由于需要为它们找到一组连续的区域,因此可能会在所有 Java 堆内存耗尽之前发生 Full GC。在这种情况下,潜在的选项是通过使用选项 -XX:G1HeapRegionSize 来减少巨大对象的数量或增加堆的大小来增加堆区域的大小。在极端情况下,即使可用内存另有指示,也可能没有足够的连续空间可供 G1 分配对象。如果 Full GC 无法回收足够的连续空间,这将导致 VM 退出。因此,除了减少前面提到的庞大对象分配的数量或增加堆外,别无选择。

调整延迟

本节讨论在常见延迟问题(即暂停时间太长)的情况下改进 G1 行为的提示。

异常系统或实时使用

对于每次垃圾收集暂停,gc+cpu=info日志输出都包含一行信息,其中包含来自操作系统的信息,并详细说明暂停时间已花费的时间。这种输出的一个例子是User=0.19s Sys=0.00s Real=0.01s.

用户时间是花在 VM 代码上的时间, system time 是在操作系统中花费的时间,以及 real time是暂停期间经过的绝对时间量。如果系统时间相对较长,那么最常见的原因是环境。

高系统时间的常见已知问题有:

  • VM 从操作系统内存中分配或返还内存可能会导致不必要的延迟。通过使用选项-Xms和将最小和最大堆大小设置为相同的值来避免延迟 -Xmx,并使用预接触所有内存-XX:+AlwaysPreTouch来将此工作移至 VM 启动阶段。
  • 特别是在 Linux 中,通过透明大页面 (THP)功能将小页面合并为大页面往往会导致随机进程停止,而不仅仅是在暂停期间。由于 VM 分配和维护大量内存,因此 VM 将成为长时间停滞的进程的风险高于平常。有关如何禁用透明大页面功能的信息,请参阅操作系统的文档。
  • 由于某些后台任务间歇性地占用了写入日志的硬盘的所有 I/O 带宽,因此写入日志输出可能会停止一段时间。考虑为您的日志或其他一些存储使用单独的磁盘,例如内存支持的文件系统以避免这种情况。

另一种需要注意的情况是实时时间远大于其他情况的总和,这可能表明 VM 在可能过载的机器上没有获得足够的 CPU 时间。

引用对象处理时间太长

有关处理参考对象所需时间的信息显示在参考处理阶段。在引用处理阶段,G1根据特定类型的引用对象的要求更新引用对象的引用。默认情况下,G1尝试使用以下启发式方法并行化引用处理的子阶段:对于每个-XX:ReferencesPerThread引用对象启动一个单独的线程,由-XX:ParallelGCThreads中的值限定。可以通过将-XX:ReferencesPerThread设置为0来禁用这种启发式,默认情况下使用所有可用的线程,或者通过-XX:-ParallelRefProcEnabled完全禁用并行化。

Young-Only 阶段的 Young-Only 集合耗时太长

正常的年轻集合,一般来说,任何年轻的集合所花费的时间大致与年轻代的大小成正比,或者更具体地说,集合集中需要复制的活动对象的数量。如果Evacuate Collection Set阶段花费的时间太长,尤其是Object Copy子阶段,请减少-XX:G1NewSizePercent。这减少了年轻代的最小大小,允许可能更短的暂停。

如果应用程序性能,特别是在集合中存活的对象数量突然发生变化,则可能会出现与年轻代大小有关的另一个问题。这可能会导致垃圾收集暂停时间出现峰值。使用 减少最大年轻代大小可能会很有用-XX:G1MaxNewSizePercent。这限制了年轻代的最大大小以及暂停期间需要处理的对象数量。

混合收集耗时太长

混合收集用于回收老年代的空间。混合收集包含年轻代和年老代区域。您可以通过启用gc+ergo+cset=trace日志输出来获取有关年轻代或年老代区域的疏散时间对暂停时间的信息。分别查看年轻代和年老代区域的预测年轻区域时间和预测年老区域时间。

如果预测的年轻区域时间太长,请参上面的”Young-Only阶段的Young_Only集合耗时太长”以获取选项。否则,为了减少老年代区域对暂停时间的处理,G1 提供了三个选项:

  • 通过增加-XX:G1MixedGCCountTarget =8(默认) 反复执行混合回收8次,每次回收受MaxGCPauseMillis的影响可能一次性回收不了所有垃圾,增加次数才能回收的更彻底。如果值设置的过小则每次回收的STW时间会延长。

  • -XX:G1MixedGCLiveThresholdPercent =85(默认) 若要回收的region区存活的对象空间占用达到85%时不去回收此空间。

  • 提前停止老年代空间回收,这样 G1 就不会收集那么多的高占用区域。在这种情况下,增加 
    -XX:G1HeapWastePercent =5(默认) 混合回收整理出来的空闲空间占heap的5%时,结果老年代的回收

请注意,最后两个选项减少了可以为当前空间回收阶段回收空间的收集集候选区域的数量。这可能意味着 G1 可能无法在老年代回收足够的空间来持续运行。然而,稍后的空间回收阶段可能能够对它们进行垃圾收集。

高更新 RS 和扫描 RS 次数

为了使 G1 能够疏散单个老年代区域,G1 跟踪跨区域引用的位置,即从一个区域指向另一个区域的引用。指向给定区域的跨区域引用称为该区域的记忆集。移动区域的内容时,必须更新记住的集合。区域记忆集的维护大多是并发的。出于性能目的,当应用程序在两个对象之间安装新的跨区域引用时,G1 不会立即更新区域的记住集。记住的集合更新请求被延迟和批处理以提高效率。

G1 需要完整的记忆集进行垃圾收集,因此垃圾收集的更新 RS阶段处理任何未完成的记忆集更新请求。该扫描RS在记忆组对象引用阶段的搜索,移动区域中的内容,然后更新到新的位置,这些对象的引用。根据应用的不同,这两个阶段可能需要很长时间。

使用该选项调整堆区域的大小 -XX:G1HeapRegionSize会影响跨区域引用的数量以及记忆集的大小。处理区域的记住集合可能是垃圾收集工作的重要组成部分,因此这对可实现的最大暂停时间有直接影响。较大的区域往往具有较少的跨区域引用,因此处理它们所花费的相对工作量会减少,但同时,较大的区域可能意味着每个区域要疏散更多的活动对象,从而增加了其他阶段的时间。

G1 尝试调度记忆集更新的并发处理,以便更新 RS 阶段占用大约-XX:G1RSetUpdatingPauseTimePercent允许的最大暂停时间的百分比。通过减小这个值,G1 通常会同时执行更多的记忆集更新工作。

伪高更新RS时间与应用程序分配大对象的结合可能是由优化引起的。什么优化?尝试通过批处理来减少并发记住的集更新工作。
如果创建此类批处理的应用程序恰好发生在垃圾收集之前,那么垃圾收集必须在暂停的Update RS时间部分处理所有这些工作。
使用-XX:-ReduceInitialCardMarks禁用此行为并可能避免这些情况。

扫描 RS 时间也由 G1 执行的压缩量决定,以保持记住的设置存储大小较低。记住的集合存储在内存中越紧凑,在垃圾回收期间检索存储的值所需的时间就越多。G1 自动执行这种压缩,称为记忆集粗化,同时根据该区域记忆集的当前大小更新记忆集。特别是在最高压缩级别下,检索实际数据可能会非常缓慢。-XX:G1SummarizeRSetStatsPeriod gc+remset=trace级别记录结合的选项显示是否发生这种粗化。如果是这样,则Before GC Summary部分中的行Did <X> coarsenings中的 将显示高值。这-XX:G1RSetRegionEntries可以显着增加选项以减少这些粗化的数量。避免在生产环境中使用这种详细的记住设置日志,因为收集这些数据可能需要大量时间。

调整吞吐量

G1 的默认策略试图在吞吐量和延迟之间保持平衡;但是,在某些情况下需要更高的吞吐量。除了如前几节所述减少总体停顿时间外,还可以减少停顿的频率。主要思想是通过使用增加最大暂停时间-XX:MaxGCPauseMillis。代大小启发式会自动适应年轻代的大小,这直接决定了暂停的频率。如果这不会导致预期的行为,特别是在空间回收阶段,增加最小年轻代大小 -XX:G1NewSizePercent将迫使 G1 这样做。

在某些情况下,-XX:G1MaxNewSizePercent允许的最大年轻代大小可能会通过限制年轻代大小来限制吞吐量。这可以通过查看gc+heap=info日志记录的区域摘要输出来诊断。在这种情况下,伊甸园区域和幸存者区域的组合百分比接近区域-XX:G1MaxNewSizePercent总数的百分比。-XX:G1MaxNewSizePercent在这种情况下考虑增加。

增加吞吐量的另一个选择是尝试减少并发工作量,特别是并发记忆集更新通常需要大量 CPU 资源。增加 -XX:G1RSetUpdatingPauseTimePercent将工作从并发操作转移到垃圾收集暂停。在最坏的情况下,可以通过设置禁用并发记住的集合更新-XX:-G1UseAdaptiveConcRefinement -XX:G1ConcRefinementGreenZone=2G -XX:G1ConcRefinementThreads=0。这主要是禁用此机制并将所有记住的集合更新工作移动到下一个垃圾收集暂停。

通过 using 启用大页面的使用-XX:+UseLargePages也可以提高吞吐量。有关如何设置大页面的信息,请参阅操作系统文档。

您可以通过禁用它来最小化堆大小调整工作;将选项-Xms -Xmx 设置为相同的值。此外,您可以使用-XX:+AlwaysPreTouch将操作系统工作移回虚拟内存与物理内存到 VM 启动时。为了使暂停时间更加一致,这两种措施都是特别需要的。

调整堆大小

与其他收集器一样,G1 旨在调整堆大小,以便垃圾收集所花费的时间低于由-XX:GCTimeRatio选项确定的比率。调整此选项以使 G1 满足您的要求。

可调默认值

本节介绍有关本主题中介绍的命令行选项的默认值和一些附加信息。

选项和默认值 描述

-XX:+G1UseAdaptiveConcRefinement

-XX:G1ConcRefinementGreenZone=<ergo>

-XX:G1ConcRefinementYellowZone=<ergo>

-XX:G1ConcRefinementRedZone=<ergo>

-XX:G1ConcRefinementThreads=<ergo>

并发记忆集更新(细化)使用这些选项来控制并发细化线程的工作分配。G1 为这些选项选择符合人体工程学的值,以便-XX:G1RSetUpdatingPauseTimePercent在垃圾收集暂停中花费时间来处理任何剩余的工作,并根据需要自适应地调整它们。请谨慎更改,因为这可能会导致非常长的停顿。

-XX:+ReduceInitialCardMarks

这将用于初始对象分配的并发记忆集更新(细化)工作批处理在一起。

-XX:+ParallelRefProcEnabled

-XX:ReferencesPerThread=1000

-XX:ReferencesPerThread确定并行度:对于每N 个参考对象,一个线程将参与参考处理的子阶段,受限于-XX:ParallelGCThreads。值 0 表示-XX:ParallelGCThreads将始终使用值所指示的最大线程数。 

这决定了是否处理 java.lang.Ref.* 实例应该由多个线程并行完成。

-XX:G1RSetUpdatingPauseTimePercent=10 

这决定了 G1 在更新 RS 阶段应该花费的总垃圾收集时间的百分比来更新任何剩余的记住集。G1 使用此设置控制并发记住集更新的数量。

-XX:G1SummarizeRSetStatsPeriod=0 

这是 G1 在许多 GC 中生成记住的集合摘要报告的时期。将此设置为零以禁用。生成记住的集合摘要报告是一项代价高昂的操作,因此应该仅在必要时使用它,并且具有相当高的价值。使用 gc+remset=trace打印任何东西。

-XX:GCTimeRatio=12 

这是应该用于垃圾收集而不是应用程序的目标时间比率的除数。确定在增加堆之前可用于垃圾收集的目标时间比例的实际公式是 1 / (1 + GCTimeRatio)。这个默认值导致目标有大约 8% 的时间花在垃圾收集上。

-XX:G1PeriodicGCInterval=0

检查 G1 是否应触发定期垃圾收集的时间间隔(以毫秒为单位)。设置为零以禁用。

-XX:+G1PeriodicGCInvokesConcurrent

如果设置,定期垃圾回收会触发并发标记或继续现有的回收周期,否则会触发 Full GC。

-XX:G1PeriodicGCSystemLoadThreshold=0.0 主机 getloadavg()调用返回的当前系统负载阈值,以确定是否应触发定期垃圾收集。当前系统负载高于此值会阻止定期垃圾回收。零值表示禁用此阈值检查。

注:<ergo> 意味着实际值是根据环境根据人体工程学确定的。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/14695.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信