【问题标题】:Switch to "-XX:+UseParNewGC -XX:+UseConcMarkSweepGC" causing more full GC切换到“-XX:+UseParNewGC -XX:+UseConcMarkSweepGC”导致更完整的 GC
【发布时间】:2023-03-27 16:35:02
【问题描述】:

我们有一个正在尝试优化延迟的应用程序,我们希望减少在完全 GC 中花费的平均时间。用 "XX:+UseParallelGC" 我们看到的是这样的:

[myhost ~]$ /usr/local/jdk7/bin/jstat -gcutil 9793 1000
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
  0.00  49.57  95.93  93.32  99.48  10086  390.628   387 1005.334 1395.962
 56.99   0.00   7.42  93.32  99.48  10087  390.691   387 1005.334 1396.025
 56.99   0.00  22.19  93.32  99.49  10087  390.691   387 1005.334 1396.025
 56.99   0.00  36.28  93.32  99.49  10087  390.691   387 1005.334 1396.025
[myhost ~]$ ps -p 9793 -o etime=
 4-12:40:52

当我们切换到使用“-XX:+UseParNewGC -XX:+UseConcMarkSweepGC”时,我们会看到更完整的 GC:

[myhost]$ /usr/local/jdk7/bin/jstat -gcutil 2514 1000
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
  0.00 100.00 100.00  99.62  24.20    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.20    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.20    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.20    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.20    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.20    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.20    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.20    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.20    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.19    716   28.151    24   44.250   72.401
  0.00 100.00 100.00  99.62  24.19    716   28.151    24   44.250   72.401
  0.00   0.00   5.92  99.44  24.19    716   28.151    24   56.361   84.512
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00 100.00  99.66  24.19    718   28.221    26   56.417   84.638
100.00   0.00  34.98  99.87  24.20    720   28.319    27   68.708   97.026
100.00   0.00 100.00  99.87  24.20    721   28.319    28   68.708   97.026
100.00   0.00 100.00  99.87  24.20    721   28.319    28   68.708   97.026
100.00   0.00 100.00  99.87  24.20    721   28.319    28   68.708   97.026
100.00   0.00 100.00  99.87  24.20    721   28.319    28   68.708   97.026

这是我们的堆设置:

 -Xms256m -Xmx8192m -XX:PermSize=128m -XX:MaxPermSize=1024m

我们正在使用 JDK:

[myhost ~]$ /usr/local/jdk7/bin/java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=261346688 -XX:MaxHeapSize=4181547008 -XX:+PrintCommandLineFlags -XX:+UseCompressedOops -XX:+UseParallelGC
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

第一个实例有 4 天以上的正常运行时间。第二个实例只持续了几分钟。我们注意到它会频繁地进行完整的 GC 并有很大的停顿,因此我们恢复了设置。

这里需要调整什么,以使 GC 统计数据不会出现问题?

【问题讨论】:

  • 你绑定到 java 7 了吗?如果您想降低 gc 暂停,那么 G1GC 可能是您的最佳选择
  • 是的,到目前为止,我们几乎都绑定到 Java 7。

标签: java java-7 jdk1.7


【解决方案1】:

在之前的捕获中,只有记录,但每个事件都有 1005 完整的 GC 时间。在您的第二次捕获中,它显示了更多记录,但每个事件只有 44~68 个完整的 GC 时间。因此,如果您总结第一次和第二次捕获的完整 GC 时间,则更改配置后的第二次实际上具有更少的完整 GC 时间。

【讨论】:

  • 第一个实例有 4 天以上的正常运行时间。第二个实例只持续了几分钟。我们注意到它在执行完整的 GC 时有很大的停顿,所以我们恢复了设置。
  • 我认为您的 jstat 不适用于 4 天以上的 GC 结果。你给了 1000 的间隔,所以 jstat 每 1 秒收集一次 gc 统计信息,直到你停止 jstat 命令或 JVM 进程被杀死。
  • 真的吗?进程启动后不收集 FGC 和 FGCT 吗?
  • 呃...我不认为 jstat 具有这些功能.. 除非 JVM 进程本身具有所有 GC 历史并将其提供给 jstat。其他最新的可视化工具(如 jconsole 或 visualvm)也是如此。当您运行该过程时,它会开始收集数据,而不是之前的数据。
  • 如果可用,也可以尝试使用 jConsole 或 VisualVM,而不是 jstat。更直观、更有用,便于追踪 GC 趋势。
【解决方案2】:

通过人体工程学,您可以提供参数,这些参数与默认的平台相关选择一起可以调整与应用程序属性相关的 GC 行为。更改收集器并没有指定调整如何影响执行的 GC 计数这一事实并不能说明收集器选择是错误的,因为问题可能是由其他原因引起的。

就行为而言,ConcMarkSweepGC 保证应用程序中的暂停时间更少,但在 GC 事件中生成任何东西。尽管您的第二个测试表明 Full GC 平均花费的时间有所改善,但您必须测试更长的时间才能了解收集器如何适应自身以满足指标。

根据最近的历史记录,并发收集器会估计在老年代耗尽之前剩余的时间以及并发收集周期所需的时间。基于这些动态估计,将启动一个并发收集周期,目的是在老年代耗尽之前完成收集周期。

除此之外,您必须运行一些案例(包括测试其他收集器)才能在 GC 所花费的时间(收集器的承诺)和执行的 GC 事件之间取得适当的平衡,您可以在那里进行测试对于可以控制对象如何提升的参数(基于代际假设),或在收集器运行之前可接受的堆使用情况,例如:

-XX:NewRatio=<N>
-XX:CMSInitiatingOccupancyFraction=<N>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-09
    • 2015-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多