根据documentation,XX:InitiatingHeapOccupancyPercent
设置触发标记周期的Java堆占用率阈值。 默认占用率是整个Java堆的45%。
在我目前的环境中,这种情况不会发生。
我的G1垃圾收集配置如下
-Xms25000m
-Xmx25000m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=1000
-XX:GCTimeRatio=99
-XX:InitiatingHeapOccupancyPercent=70
-XX:MaxTenuringThreshold=8
-XX:+UnlockExperimentalVMOptions
-XX:G1MixedGCCountTarget=16
-XX:G1OldCSetRegionThresholdPercent=3
-XX:G1NewSizePercent=30
-XX:G1RSetUpdatingPauseTimePercent=5
当一个25g的堆和一个XX:InitiatingHeapOccupancyPercent
的70%时,你会期望在18g被占用时开始一个标记周期。我拖尾垃圾收集日志并没有发生。
这是一个摘录:
{Heap before GC invocations=592 (full 0):
garbage-first heap total 25600000K, used 22802164K [0x00000001a5800000, 0x00000001a60061a8, 0x00000007c0000000)
region size 8192K, 1526 young (12500992K), 25 survivors (204800K)
Metaspace used 37386K, capacity 37948K, committed 38144K, reserved 1083392K
class space used 3948K, capacity 4080K, committed 4096K, reserved 1048576K
2016-04-20T22:06:38.272+0000: 4213.406: [GC pause (GCLocker Initiated GC) (young)
Desired survivor size 801112064 bytes, new threshold 8 (max 8)
- age 1: 98537800 bytes, 98537800 total
- age 2: 7053912 bytes, 105591712 total
- age 3: 6556320 bytes, 112148032 total
- age 4: 8836064 bytes, 120984096 total
- age 5: 5725448 bytes, 126709544 total
- age 6: 6702728 bytes, 133412272 total
- age 7: 3831920 bytes, 137244192 total
- age 8: 4166336 bytes, 141410528 total
4213.406: [G1Ergonomics (CSet Construction) start choosing CSet, _pending_cards: 184844, predicted base time: 44.67 ms, remaining time: 955.33 ms, target pause time: 1000.00 ms]
4213.406: [G1Ergonomics (CSet Construction) add young regions to CSet, eden: 1501 regions, survivors: 25 regions, predicted young region time: 21.21 ms]
4213.406: [G1Ergonomics (CSet Construction) finish choosing CSet, eden: 1501 regions, survivors: 25 regions, old: 0 regions, predicted pause time: 65.88 ms, target pause time: 1000.00 ms]
4213.475: [G1Ergonomics (Heap Sizing) attempt heap expansion, reason: recent GC overhead higher than threshold after GC, recent GC overhead: 1.40 %, threshold: 1.00 %, uncommitted: 0 bytes, calculated expansion amount: 0 bytes (20.00 %)]
, 0.0687163 secs]
[Parallel Time: 61.7 ms, GC Workers: 28]
[GC Worker Start (ms): Min: 4213406.9, Avg: 4213407.1, Max: 4213407.3, Diff: 0.4]
[Ext Root Scanning (ms): Min: 6.0, Avg: 6.2, Max: 6.4, Diff: 0.4, Sum: 173.1]
[Update RS (ms): Min: 33.5, Avg: 34.0, Max: 34.6, Diff: 1.1, Sum: 951.9]
[Processed Buffers: Min: 27, Avg: 36.6, Max: 48, Diff: 21, Sum: 1024]
[Scan RS (ms): Min: 0.1, Avg: 0.2, Max: 0.5, Diff: 0.4, Sum: 6.3]
[Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
[Object Copy (ms): Min: 20.1, Avg: 20.6, Max: 20.8, Diff: 0.7, Sum: 577.5]
[Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.7]
[Termination Attempts: Min: 1, Avg: 13.2, Max: 19, Diff: 18, Sum: 371]
[GC Worker Other (ms): Min: 0.0, Avg: 0.2, Max: 0.4, Diff: 0.3, Sum: 4.7]
[GC Worker Total (ms): Min: 60.9, Avg: 61.2, Max: 61.6, Diff: 0.6, Sum: 1714.2]
[GC Worker End (ms): Min: 4213468.2, Avg: 4213468.3, Max: 4213468.5, Diff: 0.3]
[Code Root Fixup: 0.4 ms]
[Code Root Purge: 0.0 ms]
[Clear CT: 1.2 ms]
[Other: 5.4 ms]
[Choose CSet: 0.0 ms]
[Ref Proc: 0.5 ms]
[Ref Enq: 0.0 ms]
[Redirty Cards: 0.8 ms]
[Humongous Register: 0.2 ms]
[Humongous Reclaim: 0.0 ms]
[Free CSet: 2.4 ms]
[Eden: 11.7G(11.7G)->0.0B(11.7G) Survivors: 200.0M->200.0M Heap: 21.7G(24.4G)->10.0G(24.4G)]
Heap after GC invocations=593 (full 0):
garbage-first heap total 25600000K, used 10516798K [0x00000001a5800000, 0x00000001a60061a8, 0x00000007c0000000)
region size 8192K, 25 young (204800K), 25 survivors (204800K)
Metaspace used 37386K, capacity 37948K, committed 38144K, reserved 1083392K
class space used 3948K, capacity 4080K, committed 4096K, reserved 1048576K
}
[Times: user=1.70 sys=0.01, real=0.07 secs]
2016-04-20T22:06:38.342+0000: 4213.475: Total time for which application threads were stopped: 0.0701353 seconds, Stopping threads took: 0.0001600 seconds
我会引起你的注意
{Heap before GC invocations=592 (full 0):
garbage-first heap total 25600000K, used 22802164K [0x00000001a5800000, 0x00000001a60061a8, 0x00000007c0000000)
[...]
[Eden: 11.7G(11.7G)->0.0B(11.7G) Survivors: 200.0M->200.0M Heap: 21.7G(24.4G)->10.0G(24.4G)]
在此集合之前,超过70%的堆已被占用。为什么这不会触发标记周期?
该应用程序继续进行年轻代收集,填补旧区域,最终导致分配失败和冗长的全GC。
将InitiatingHeapOccupancyPercent
减少到55没有明显的效果。
在20岁时,它确实开始进行混合收集,但只有当约80%的堆被占用时才会开始。
答案 0 :(得分:6)
JDK-6976060表明在年轻的GC结束时需要计算标记周期。根据它是否使用年轻GC之前或之后的占用统计数据,这可能意味着也可能不意味着伊甸园空间总是被视为占用IHOP计算的0%。拥有45%的伊甸园大小意味着永远不会达到70%的占用率,最大可能占用率将达到55%,此时堆将完全填满,对于混合收集来说为时已晚。
但我怀疑这是否真的如此,因为面对动态的年轻一代规模,这会使文档误导,IHOP调整更加困难。使用人工测试用例和手动调整代数来验证这一点应该相当容易。
如果那不是问题,那么GC pause (GCLocker Initiated GC) (young)
可能会指向bug 8140597,这已在jdk9b94中修复。
更新:Bug 8151176中的描述确实表明,为了IHO百分比计算,它计算oldgen占用率/总堆大小。这意味着年轻一代的入住率被完全忽略,这反过来又意味着年轻人的分数> IHOP然后它永远不会启动并发周期。
原因是如果旧的占用率超过当前堆容量的固定百分比,则静态IHOP启动。如果用户或人体工程学决定旧的gen不能大于触发并发标记的堆容量的那一部分,则标记将永远不会开始。
目前可用的解决方案是