当前位置: 首页 > 知识库问答 >
问题:

为什么G1GC在开始混合收藏之前会缩减年轻一代?

丁宏盛
2023-03-14

当G1决定需要开始进行混合收集时,它会积极地将我们的伊甸园空间从10g缩小到1g左右。

{Heap before GC invocations=294 (full 0):
 garbage-first heap   total 20480000K, used 18304860K [0x00000002de000000, 0x00000002de804e20, 0x00000007c0000000)
  region size 8192K, 1363 young (11165696K), 11 survivors (90112K)
 Metaspace       used 37327K, capacity 37826K, committed 38096K, reserved 1083392K
  class space    used 3935K, capacity 4081K, committed 4096K, reserved 1048576K
2016-03-31T20:57:31.002+0000: 7196.427: [GC pause (G1 Evacuation Pause) (young)
Desired survivor size 717225984 bytes, new threshold 1 (max 1)
- age   1:   41346816 bytes,   41346816 total
 7196.427: [G1Ergonomics (CSet Construction) start choosing CSet, _pending_cards: 144693, predicted base time: 48.88 ms, remaining time: 951.12 ms, target pause time: 1000.00 ms]
 7196.427: [G1Ergonomics (CSet Construction) add young regions to CSet, eden: 1352 regions, survivors: 11 regions, predicted young region time: 20.72 ms]
 7196.427: [G1Ergonomics (CSet Construction) finish choosing CSet, eden: 1352 regions, survivors: 11 regions, old: 0 regions, predicted pause time: 69.60 ms, target pause time: 1000.00 ms]
 7196.494: [G1Ergonomics (Mixed GCs) start mixed GCs, reason: candidate old regions available, candidate old regions: 789 regions, reclaimable: 4703761904 bytes (22.43 %), threshold: 5.00 %]
, 0.0673540 secs]
   [Parallel Time: 60.1 ms, GC Workers: 18]
      [GC Worker Start (ms): Min: 7196427.8, Avg: 7196428.1, Max: 7196428.2, Diff: 0.4]
      [Ext Root Scanning (ms): Min: 7.3, Avg: 7.5, Max: 7.7, Diff: 0.4, Sum: 134.2]
      [Update RS (ms): Min: 28.2, Avg: 28.8, Max: 29.9, Diff: 1.7, Sum: 518.4]
         [Processed Buffers: Min: 41, Avg: 57.7, Max: 80, Diff: 39, Sum: 1039]
      [Scan RS (ms): Min: 0.1, Avg: 0.2, Max: 0.5, Diff: 0.4, Sum: 3.7]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
      [Object Copy (ms): Min: 22.1, Avg: 23.1, Max: 23.4, Diff: 1.3, Sum: 416.2]
      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
         [Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 18]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.1, Max: 0.2, Diff: 0.2, Sum: 2.5]
      [GC Worker Total (ms): Min: 59.5, Avg: 59.7, Max: 60.0, Diff: 0.5, Sum: 1075.1]
      [GC Worker End (ms): Min: 7196487.7, Avg: 7196487.8, Max: 7196487.9, Diff: 0.2]
   [Code Root Fixup: 0.2 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 1.9 ms]
   [Other: 5.2 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.5 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.5 ms]
      [Humongous Register: 0.2 ms]
      [Humongous Reclaim: 0.1 ms]
      [Free CSet: 2.3 ms]
   [Eden: 10.6G(10.6G)->0.0B(848.0M) Survivors: 88.0M->152.0M Heap: 17.5G(19.5G)->7128.3M(19.5G)]
Heap after GC invocations=295 (full 0):
 garbage-first heap   total 20480000K, used 7299344K [0x00000002de000000, 0x00000002de804e20, 0x00000007c0000000)
  region size 8192K, 19 young (155648K), 19 survivors (155648K)
 Metaspace       used 37327K, capacity 37826K, committed 38096K, reserved 1083392K
  class space    used 3935K, capacity 4081K, committed 4096K, reserved 1048576K
}
 [Times: user=1.09 sys=0.00, real=0.07 secs]
2016-03-31T20:57:31.070+0000: 7196.495: Total time for which application threads were stopped: 0.0699324 seconds, Stopping threads took: 0.0003462 seconds

这是在它与10-11克伊甸园一起运行了60个或更多系列之后。

下面是我们运行时使用的适当的JVM GC参数

-Xms20000m -Xmx20000m
-XX:+UseG1GC 
-XX:G1RSetUpdatingPauseTimePercent=5 
-XX:MaxGCPauseMillis=1000 
-XX:GCTimeRatio=99 
-XX:InitiatingHeapOccupancyPercent=35 
-XX:MaxTenuringThreshold=1 
-XX:G1ConcRefinementThreads=6 
-XX:ConcGCThreads=18 
-XX:ParallelGCThreads=18

-XX:+PrintGCDetails"
-XX:+PrintGCDateStamps"
-XX:+PrintHeapAtGC"
-XX:+PrintTenuringDistribution"
-XX:+PrintGCApplicationStoppedTime"
-XX:+PrintPromotionFailure"
-XX:+PrintAdaptiveSizePolicy"

根据本演示文稿的第55页,它需要调整Eden的大小,以便最大暂停目标占整个堆,而不仅仅是新一代。为什么收集器如此激进?

对于10g大小的堆,年轻一代的平均暂停时间在50-150ms之间。如果演示是正确的(我还没有找到任何其他东西来支持这一说法),我希望缩小一半(20g堆),而不是10倍。

共有2个答案

白通
2023-03-14

当maxtenUringReshold=1时,您告诉GC在仅存活1个GC周期后将对象升级到旧代。在大多数应用程序中,这将导致许多过早的升级。如果太多的物品被过早地推广,你的老一代将迅速成长,因此必须缩小你的老一代,为老一代腾出空间

郑和泰
2023-03-14

您可以在第56张幻灯片中找到问题的答案

年轻一代减少了20倍

因此,缩小10倍的工厂规模并不奇怪。

来自Monica Beckwith关于调整G1GC的技巧的infoQ文章:

通过让托儿所/年轻一代缩小到默认的最小值(占总Java堆的5%),可以避免完整的GC

由于尚未明确设置年轻世代的大小,因此默认值为

-XX:G1NewSizePercent=5

将堆的百分比设置为年轻一代大小的最小值。

所以要尊重你的暂停时间目标

-XX:MaxGCPauseMillis=1000 

年轻一代可以缩小到总堆的5%。

我在谷歌上找到了一篇关于G1GC的好文章https://groups.google.com/a/jclarity.com/forum/#!msg/friends/hsZiz6HTm9M/klrRjBclCwAJ

如果G1预测的暂停时间目标大于目标暂停时间目标,那么收缩年轻一代,但不超过当前Java堆大小的G1NewSizePercent,(不是最大大小)。同样,整体Java堆将根据计算的GC时间比值GCTimeRatio增长(或收缩)。

注意:G1NewSizePercent和G1MaxNewSizePercent不要与NewSize或MaxNewSize混淆。

G1NewSizePercent和G1MaxNewSizePercent分别给出了G1可以容纳多小或多大年轻一代的下限和上限。

另一方面,您配置了许多参数,如果大多数默认参数已设置为默认值,这些参数可能是不必要的正弦G1GC可以正常工作。有关更多详细信息,请参阅此SE问题。

Java 7(JDK 7)垃圾收集和G1上的文档

总结:根据暂停时间目标,young gen会缩小。如果您真的担心young gen缩小到低值,请配置-XX: G1NewSizePercent。但只要满足-XX: MaxGCPauseMillis,我就不推荐它

编辑:

从G1GC人体工程学页面,

当垃圾收集器试图满足相互竞争的目标时,堆的大小通常会振荡。即使应用程序已达到稳定状态,也是如此。实现吞吐量目标(可能需要更大的堆)的压力与最大暂停时间和最小占用空间(两者都可能需要较小的堆)的目标相竞争。

 类似资料:
  • 据我所知,CMS collector收集老一代,它与ParNew collector(用于收集年轻一代)一起工作。对我来说,要清楚地理解CMS是如何工作的并不容易,但以下是我的看法: 1)初始标记。寻找根引用。由于收集器是旧的收集器,它应该只扫描旧的一代。 2) 并发标记找到所有根引用后,是时候开始并发标记了。从第一阶段中标记的对象可传递到达的所有对象都在该阶段中标记。 3) 并发预清理gc查看C

  • 这里有我的GC.log的摘录: 2013-02-28T12:02:13.209+0100:1486457.849:[GC 1486457.850:[ParNew 3483368K->96838K(3774912K),0.2273030秒]8085678K->4710336K(49912256K),0.2278070秒][times:user=1.54 sys=0.01,real=0.23秒] 20

  • 从…起https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#counting--: 返回一个接受类型为的元素,该采集器统计输入元素的数量。如果不存在任何元素,则结果为0。 实施要求: 这将产生相当于以下结果: 为什么这个收藏家收集成一个长的?是因为它可以在各种平台上进行优化,其中?还是我错过了什么?具有

  • 那么,我们是否可以仅使用选项运行JVM?我的意思是没有任何为年轻一代描述垃圾收集器的选项。如果我们能那样做,哪一个垃圾收集器将用于老一代?

  • 我在尝试理解垃圾收集机制,我在研究代际算法,我有一个关于年轻人和老年人的代沟的问题。我读到,在年轻一代开始收集物品,GC是从GC根开始标记它们,以找到活的,通常它会将它们复制到幸存者空间,清除年轻一代区域,然后瞧。 我不明白,如果我们从GC根开始,我们开始遍历活动对象,我们不是也在旧一代中找到了对象吗?这是否意味着,当我们击中旧空间中的一个物体时,我们会在那个点上停止跟踪参照物?

  • 如果我错了,请随时指正。在JVM堆中,有老一代和年轻一代两代。在做全GC时,在老一代中,有像紧凑空间和修复漏洞这样的繁重操作,这会使JVM挂起。而我发现在年轻一代中,应用了一个轻量级的GC,从我的搜索结果中还有一个叫做Eden的区域涉及年轻一代。但是,在搜索了很多文档后,我对年轻一代中的GC仍然有两个困惑, 在年轻一代中,GC似乎不像老一代GC那样工作(即老一代GC压缩并修复漏洞)?如果是这样,年