【问题标题】:JVM G1GC's mixed gc not collecting much old regionsJVM G1GC 的混合 gc 没有收集太多旧区域
【发布时间】:2017-04-02 11:56:02
【问题描述】:

我的服务器在 CentOS 6.7 上使用 1.8.0_92,GC 参数是 '-Xms16g -Xmx16g -XX:+UseG1GC'。所以默认的 InitiatingHeapOccupancyPercent 是 45,G1HeapWastePercent 是 5,G1MixedGCLiveThresholdPercent 是 85。我的服务器的混合 GC 从 7.2GB 开始,但是它清理的越来越少,最后老一代保持大于 7.2GB,所以它总是尝试做并发标记。最后,所有堆都用尽了,发生了完整的 GC。完全 GC 后,使用的 old gen 小于 500MB。

我很好奇为什么我的混合 GC 不能收集更多,看起来实时数据没有那么多......

我试过打印g1相关信息,发现很多类似下面的消息,看起来我的老一代包含很多实时数据,但是为什么full GC可以收集这么多......

G1Ergonomics (Mixed GCs) do not continue mixed GCs, reason: reclaimable percentage not over threshold, candidate old regions: 190 regions, reclaimable: 856223240 bytes (4.98 %),  threshold: 5.00 %

下面的日志是修改 InitiatingHeapOccupancyPercent 为 15(在 2.4GB 开始并发标记)以加快速度的结果。

### PHASE Post-Marking
......
### SUMMARY  capacity: 16384.00 MB  used: 2918.42 MB / 17.81 %  prev-live: 2407.92 MB / 14.70 %  next-live: 2395.00 MB / 14.62 %  remset: 56.66 MB  code-roots: 0.91 MB
### PHASE Post-Sorting
....
### SUMMARY  capacity: 1624.00 MB  used: 1624.00 MB / 100.00 %  prev-live: 1123.70 MB / 69.19 %  next-live: 0.00 MB / 0.00 %  remset: 35.90 MB  code-roots: 0.89 MB

编辑:

我尝试在混合 GC 之后触发 full GC,它仍然可以减少到 4xx MB,所以看起来我的老一代有更多的数据可以收集。

full gc之前,混合gc日志是

 32654.979: [G1Ergonomics (Mixed GCs) start mixed GCs, reason: candidate old regions available, candidate old regions: 457 regions, reclaimable: 2956666176 bytes (17.21 %), threshold: 5.00 %], 0.1106810 secs]
 ....
 [Eden: 6680.0M(6680.0M)->0.0B(536.0M) Survivors: 344.0M->280.0M Heap: 14.0G(16.0G)->7606.6M(16.0G)]
 [Times: user=2.31 sys=0.01, real=0.11 secs]
 ...
 [GC pause (G1 Evacuation Pause) (mixed)
 ...
 32656.876: [G1Ergonomics (CSet Construction) finish adding old regions to CSet, reason: old CSet region num reached max, old: 205 regions, max: 205 regions]
 32656.876: [G1Ergonomics (CSet Construction) finish choosing CSet, eden: 67 regions, survivors: 35 regions, old: 205 regions, predicted pause time: 173.84 ms, target pause time: 200.00 ms]
 32656.992: [G1Ergonomics (Mixed GCs) continue mixed GCs, reason: candidate old regions available, candidate old regions: 252 regions, reclaimable: 1321193600 bytes (7.69 %), threshold: 5.00 %]
 [Eden: 536.0M(536.0M)->0.0B(720.0M) Survivors: 280.0M->96.0M Heap: 8142.6M(16.0G)->6029.9M(16.0G)]
 [Times: user=2.49 sys=0.01, real=0.12 secs]
 ...
 [GC pause (G1 Evacuation Pause) (mixed)
 ...
 32659.727: [G1Ergonomics (CSet Construction) finish adding old regions to CSet, reason: reclaimable percentage not over threshold, old: 66 regions, max: 205 regions, reclaimable: 857822432 bytes (4.99 %), threshold: 5.00 %]
 32659.727: [G1Ergonomics (CSet Construction) finish choosing CSet, eden: 90 regions, survivors: 12 regions, old: 66 regions, predicted pause time: 120.51 ms, target pause time: 200.00 ms]
 32659.785: [G1Ergonomics (Mixed GCs) do not continue mixed GCs, reason: reclaimable percentage not over threshold, candidate old regions: 186 regions, reclaimable: 857822432 bytes (4.99 %), threshold: 5.00 %]
 [Eden: 720.0M(720.0M)->0.0B(9064.0M) Survivors: 96.0M->64.0M Heap: 6749.9M(16.0G)->5572.0M(16.0G)]
 [Times: user=1.20 sys=0.00, real=0.06 secs]

编辑: 2016/12/11

我已经用-Xmx4G从另一台机器上转储了堆。

我使用 lettuce 作为我的 redis 客户端,它使用 LatencyUtils 具有跟踪功能。它使 LatencyStats(其中包含一些具有近 3000 个元素的 long[])实例每 10 分钟弱引用一次(默认情况下,发布后重置延迟为 true,https://github.com/mp911de/lettuce/wiki/Command-Latency-Metrics)。所以时间长了会造成很多对LatencyStats的弱引用。

在完全 GC 之前。

Full GC 之后。

目前我不需要对生菜进行跟踪,因此只需禁用它,它就不再具有完整的 GC。但不知道为什么混合 gc 不能清除它们。

【问题讨论】:

  • -XX:+UnlockDiagnosticVMOptions -XX:+G1PrintHeapRegions -XX:+G1PrintRegionLivenessInfo 可能会提供一些见解。我猜你得到了巨大的分配或一些分配模式以某种方式导致不正确的活跃度估计(可能是软参考)?
  • 谢谢,### PHASE Post-Marking 是 G1PrintRegionLivenessInfo,看起来它还有超过 1GB 的实时数据。并且巨大的没有显示很多[Humongous Total: 1] [Humongous Candidate: 1]。我将检查如何知道它是否来自软引用 ..(有关此的任何文档?)
  • 我会试试SoftRefLRUPolicyMSPerMB..
  • hmm 添加 SoftRefLRUPolicyMSPerMB 后不起作用
  • 那么你应该在某处上传 gc 日志。或尝试降低G1MixedGCLiveThresholdPercent

标签: java garbage-collection weak-references g1gc


【解决方案1】:

嗯,你没有提到你设置的所有参数,但是

你可以尝试设置

-XX:+ScavengeBeforeFullGC

您还应该考虑您的Objects 生命周期。您的应用程序Objects 可以存活多久,Objects 的大小是多少。

想一想,看看下面的论点

-XX:NewRatio=n              old/new ration (default 2)
-XX:SurvivorRatio=n         eden/survivor ratio (default 8)
-XX:MaxTenuringThreshold=n  number of times, objects are moved from survivor one to survivor two and vice versa before objects are moved to old-gen (default 15)

使用默认值 Xms 和 Xmx 设置为 32gb -> old gen = 16gb 和 new gen 16gb -> eden 14gb -> 幸存者 2gb(有两个,每个大小为 1gb)

eden 包含由new Object 实例化的所有Objects。

一个幸存者(对幸存者)总是空的。其他的(来自幸存者)包含在次要 gc 中幸存的Objects

从 eden 和 from-survivor 中幸存的Objects 在次要 gc 中进入 to-survivor

如果此“默认配置”的 1gb 标准大小超过,Objects 进入旧代

如果不超过,在 15 个次要 gc 之后(-XX:MaxTenuringThresholds 默认值),Objects 进入 old-gen

通过调整这些值,请始终牢记,old-gen 必须与 new-gen 一样大或更大,因为 gc 可能会导致整个 new-gen 进入 old-gen

编辑

您的第一张“老一代:二手”图片的时间线会有所帮助

请记住,在 old gen 不超过之前没有必要执行完整 gc - 完整 gc 会导致整个“世界”停止一段时间

在这种特殊情况下,我会说你可以

  1. -Xms-Xmx 减少到8gb
  2. -XX:SurvivorRatios 的值设置/减小为 2
  3. -XX:MaxTenuringThreshold 设置/增加至50

你会得到一个新旧版本,每个大小 4gb,

eden 大小为 2gb,

两个幸存者,每个大小 1gb,

Objects 进入旧代之前,大约有 50 个次要 gc

【讨论】:

  • -XX:NewRatio=n old/new ration (default 2) with default values Xms and Xmx is set to 32gb -> old gen = 22gb and new gen 11g大约
猜你喜欢
  • 1970-01-01
  • 2016-07-20
  • 1970-01-01
  • 2020-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-18
相关资源
最近更新 更多