java - G1 GC——极长的终止时间

标签 java garbage-collection g1gc

G1 GC 有时会在终止阶段花费大量时间。正如您所看到的,GC 工作线程平均时间为 442.9,终止时间为 327.3。 这是处理大量消息的高性能低延迟应用程序。事件处理数据必须由 yong gc 收集。通常事件处理时间不超过 150 毫秒。

硬件:x24 Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz,32Gb 内存,8Gb 内存免费 JVM 选项:-server -XX:+UseG1GC -XX:MaxGCPauseMillis=60 -XX:ParallelGCThreads=24 -Xmx12g -Xms12g -Xss256k Linux 2.6.32-696.6.3.el6.x86_64 java版本“1.8.0_102”

通常 G1 将新大小设置为 7Gb,年轻 GC 暂停为 50 毫秒,终止时间仅为 6 毫秒,收集之间的间隔为 3 秒。

如果应用程序生成大量长期存在的对象,那么年轻的暂停可能会增加,这也会导致年轻 GC 大小的减少。但在这种情况下,终止时间保持不变。我想知道为什么终止时间会急剧增加。

另请注意此暂停的大系统时间。通常GC暂停的系统时间是0-10ms。对于这个,它是 1 秒。

2017-08-23T13:21:37.690-0400: 1509.022: [GC pause (G1 Evacuation Pause) (young), 0.4474119 secs]
   [Parallel Time: 443.2 ms, GC Workers: 24]
      [GC Worker Start (ms): Min: 1509022.9, Avg: 1509023.0, Max: 1509023.4, Diff: 0.4]
      [Ext Root Scanning (ms): Min: 2.1, Avg: 22.5, Max: 90.4, Diff: 88.3, Sum: 539.7]
      [Update RS (ms): Min: 0.0, Avg: 2.2, Max: 5.0, Diff: 5.0, Sum: 54.0]
         [Processed Buffers: Min: 0, Avg: 24.7, Max: 67, Diff: 67, Sum: 592]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.7]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Object Copy (ms): Min: 26.1, Avg: 106.1, Max: 435.6, Diff: 409.6, Sum: 2545.3]
      [Termination (ms): Min: 0.0, Avg: 312.0, Max: 327.3, Diff: 327.3, Sum: 7488.6]
         [Termination Attempts: Min: 1, Avg: 1.5, Max: 4, Diff: 3, Sum: 36]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.0, Sum: 0.6]
      [GC Worker Total (ms): Min: 442.5, Avg: 442.9, Max: 443.0, Diff: 0.5, Sum: 10628.9]
      [GC Worker End (ms): Min: 1509465.9, Avg: 1509465.9, Max: 1509465.9, Diff: 0.1]
   [Code Root Fixup: 0.4 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.3 ms]
   [Other: 3.6 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 1.5 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.4 ms]
      [Humongous Register: 0.2 ms]
      [Humongous Reclaim: 0.1 ms]
      [Free CSet: 0.3 ms]
   [Eden: 476.0M(476.0M)->0.0B(556.0M) Survivors: 136.0M->56.0M Heap: 4480.6M(12.0G)->4016.3M(12.0G)]
 [Times: user=4.23 sys=1.08, real=0.45 secs]

最佳答案

我有一个建议。有时,当系统上运行其他进程时,它们会与您的 Java GC 工作线程竞争。

[对象复制(毫秒):最小值:26.1,平均值:106.1,最大值:435.6,差异:409.6,总和:2545.3] [外根扫描(毫秒):最小值:2.1,平均值:22.5,最大值:90.4,差异:88.3,总和:539.7]

从上面的日志来看,GC 工作线程似乎正在做不成比例的工作。这意味着大多数 GC 线程提前完成,其中一些仍在工作。当这种情况发生时,已完成的线程会尝试窃取其他线程的工作。这反射(reflect)在终止时间上。因此,终止时间不是原因,而只是副作用。

[终止(毫秒):最小值:0.0,平均值:312.0,最大值:327.3,差异:327.3,总和:7488.6]

您有一台 24 核机器,有 24 个 GC 工作线程。如果有其他进程或系统 Activity 需要 CPU 资源,则很可能某些 GC 工作线程会因争用而被延迟安排。

值得尝试将线程数量减少到 18 个并尝试一下。

您还可以增加 gc 日志级别,执行此操作时,它会打印每个线程的启动时间。这有助于调试应用程序。

关于java - G1 GC——极长的终止时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45848433/

相关文章:

java - Eclipse clean 删除了我的大部分导入语句

java - 为什么启用 G1 垃圾收集器时最大堆大小不正确?

java - 为什么 G1 垃圾收集器卸载时间随着时间的推移而增加?

java - G1 和 CMS 的 UseCompressedOops 启动阈值不同

go - goroutine不会将内存返回操作系统

Java不是垃圾收集内存

java - 具有方法访问检测的 Python 抽象属性

java - Swing 中的重叠组件

java - 基于Object Class的hashcode实现

spring-boot - Apache 点燃: Possible too long JVM pause: 714 milliseconds