Java 并行 GC 调优

并行垃圾收集器(Parallel GC)是 JVM 中引入的最古老的垃圾收集算法之一,旨在利用现代多核系统的处理能力。并行GC旨在通过利用多个线程并行执行垃圾收集来减少GC暂停的影响。

什么时候使用并行GC?
如果您有以下任何一项要求,您可以考虑在您的应用程序中使用并行 GC:

  1. 强调吞吐量:如果您的应用程序具有较高的事务吞吐量要求,并且可以容忍长时间、偶尔的垃圾收集暂停,那么并行 GC 可能是一个合适的选择。它专注于通过允许垃圾收集与应用程序执行同时发生来最大化吞吐量。
  2. 批处理:涉及批处理或数据分析任务的应用程序可以从并行 GC 中受益。这些类型的应用程序通常执行大量计算,并行 GC 有助于最大限度地减少垃圾收集对整体处理时间的影响。
  3. 堆大小注意事项:并行 GC 非常适合具有中等到大堆大小的应用程序。如果您的应用程序需要大量堆来满足其内存需求,并行 GC 可以有效地管理内存并减少垃圾收集暂停的影响。

如何启用并行GC?
要显式配置应用程序以使用并行 GC,您可以在启动 Java 应用程序时传递以下参数:

-XX:+UseParallelGC
此 JVM 参数指示 JVM 使用并行 GC 算法进行垃圾收集。但请注意,如果您没有显式指定垃圾收集算法,则在 Java 8 之前的所有服务器类 JVM 中,默认垃圾收集器都会设置为并行 GC。

并行 GC JVM 参数

1、堆和生成大小参数

  • -Xmx:该参数设置最大堆大小,它建立了内存分配的上限。通过仔细选择合适的-Xmx值,开发人员可以控制总体堆大小,以在内存可用性和 GC 性能之间取得平衡。
  • -XX:NewSize 和 -XX:MaxNewSize 或 -XX:NewRatio:这些参数控制分配新对象的年轻代的大小。-XX:NewSize设置初始大小,而-XX:MaxNewSize或-XX:NewRatio分别控制年轻代和长期代之间的上限或比例。调整这些值可以微调年轻代的大小和比例。缩小了年轻代的大小,可显着改善了整体应用程序的响应时间。
  • -XX:YoungGenerationSizeIncrement 和 -XX:TenuredGenerationSizeIncrement:这些参数分别定义了年轻代和长期代的大小增量。年轻代和长期代的大小增量是内存分配和垃圾回收行为的关键因素。增长和缩小的速度各不相同。默认情况下,一代的增长增量为 20%,收缩增量为 5%。增长的百分比由命令行选项 -XX:YoungGenerationSizeIncrement=<Y> 和 -XX:TenuredGenerationSizeIncrement=<T> 控制。
  • -XX:AdaptiveSizeDecrementScaleFactor:该参数用于确定在缩减代大小时使用的缩放因子。一代缩减的百分比由命令行标志 -XX:AdaptiveSizeDecrementScaleFactor=<D> 调整。如果增长增量为 X%,则缩小时的递减量为 X/D%。

2、基于目标的调整参数
为了实现垃圾收集的最佳性能,控制 GC 暂停时间和优化 GC 吞吐量至关重要,GC 吞吐量表示与应用程序执行相比专用于垃圾收集的时间量。在本节中,我们将探讨有助于基于目标的调整的关键 JVM 参数,使开发人员能够微调垃圾收集的这些方面。

  • -XX:MaxGCPauseMillis:此参数使开发人员能够指定垃圾收集所需的最大暂停时间(以毫秒为单位)。通过设置适当的值,开发人员可以调节 GC 暂停的持续时间,确保它们保持在可接受的限制内。
  • -XX:GCTimeRatio:此参数使用公式1 / (1 + N)设置垃圾收集时间与应用程序时间的比率,其中 N 是正整数值。此参数的目的是定义与应用程序执行时间相比所需的垃圾收集时间分配,以优化 GC 吞吐量。例如,让我们考虑 -XX:GCTimeRatio=19 的场景。使用该公式,目标是将总时间的 1/20 或 5% 分配给垃圾回收。这意味着对于组合的垃圾收集和应用程序执行的每20个时间单位(例如,毫秒),大约1个时间单位将被分配给垃圾收集,而剩余的19个时间单位将专用于应用程序执行。默认值是 99,它设置垃圾回收时间为 1% 的目标。
  • -XX:GCTimePercentage:该参数允许开发人员直接指定分配给垃圾收集的时间相对于应用程序执行时间(即GC吞吐量)的期望百分比。例如,设置“-XX:GCTimePercentage=5”表示将总时间的 5% 分配给垃圾回收的目标,其余 95% 专用于应用程序执行。 

注意:开发人员可以选择使用“ -XX:GCTimeRatio ”或“ -XX:GCTimePercentage ”作为彼此的替代选项。这两个选项都可以灵活地表达垃圾收集所需的时间分配。我更喜欢使用“-XX:GCTimePercentage”而不是“-XX:GCTimeRatio”,因为它易于理解。

3、其他参数
除了前面讨论的 JVM 参数之外,还有一些其他参数可用于调整并行 GC 算法。让我们来探索一下它们。

  • -XX:ParallelGCThreads:该参数允许开发人员指定并行GC算法中用于垃圾收集的线程数。通过根据可用的 CPU 内核设置适当的值,开发人员可以利用多核系统的处理能力来优化吞吐量。通过避免太少或太多线程来达到平衡非常重要,因为这两种情况都可能导致性能不佳。
  • -XX:-UseAdaptiveSizePolicy:默认情况下,启用“ UseAdaptiveSizePolicy ”选项,该选项允许根据应用程序的行为和内存需求动态调整年轻代和老一代的大小。然而,这种动态调整大小可能会导致频繁的“ Full GC – Ergonomics ”垃圾收集并增加 GC 暂停时间。为了缓解这个问题,我们可以传递-XX:-UseAdaptiveSizePolicy参数来禁用大小调整并减少 GC 暂停时间。

调整并行 GC 行为
研究并行 GC 的性能特征最好通过分析 GC 日志来实现。GC 日志包含有关垃圾收集事件、内存使用情况和其他相关指标的详细信息。有多种工具可以帮助分析 GC 日志,例如GCeasyIBM GC & Memory VisualizerHP JmeterGoogle Garbage cat。通过使用这些工具,您可以可视化内存分配模式、识别潜在瓶颈并评估垃圾收集的效率。这样可以在微调并行 GC 以获得最佳性能时做出明智的决策。