在 G1 中将 G1HeapWastePercent 设置为零的后果

Consequences of setting G1HeapWastePercent to zero in G1

美好的一天,我在生产中使用 G1(热点 JDK 11)并试图了解它是如何工作的。据我了解,G1 中的 Old GC 只会清理那些充满垃圾的区域,否则这些区域会被放入某个队列。

稍后触发混合 GC,它将使用 amount of Old generations/G1MixedGCCountTarget 个旧区域清理年轻区域。要扫描的旧区域由 G1MixedGCLiveThresholdPercent 确定,默认情况下为 65%,如果该区域的 65% 是垃圾,则它将被清理。

但是我不确定我是否理解G1HeapWastePercent的意思。 来自官方文档

Sets the percentage of heap that you are willing to waste. The Java >HotSpot VM does not initiate the mixed garbage collection cycle when the >reclaimable percentage is less than the heap waste percentage. The default is 10 percent. This setting is not available in Java HotSpot VM, build 23.

假设区域包含 65% 的垃圾。 G1 开始将生命对象从 Young region 移动到单个充满垃圾的 Old region,一旦这个 region 只包含 10% 的垃圾,G1 就切换到另一个 old region 区域。如果我的假设是正确的,那么将 G1HeapWastePercent 设置为 0 将用生命对象完全填充该区域。这是正确的吗 ?如果时间延迟不是我的应用程序的优先级,我将 G1HeapWastePercent 设置为零会有任何好处吗?

首先,我想你可能误解了G1MixedGCLiveThresholdPercent的作用(Jdk7默认值为65%,Jdk11默认值为85%)。 G1MixedGCLiveThresholdPercent不是垃圾对象的space比例,而是活对象的space比例。如果一个region中的存活对象space超过85%(在jdk11中),那么该region将不会被select编入 collection set(待回收区域合集)

其次,G1HeapWastePercent(Jdk7默认为10%,Jdk11默认为5% 是触发Mixed GC和退出Mixed GC的条件。 当collection set中的垃圾对象占堆分配总量的5%以上(在jdk11中)space, 将触发Mixed GC,退出Mixed GC的充分条件之一即 collection set中的垃圾对象率低于5%。

因此,如果G1HeapWastePercent设置为0%,只要回收集中有垃圾对象,就会触发Mixed GC。 那么退出Mixed GC的充分条件就会变成collection set为空, 因为每次 Mixed GC 都会从 collection set.

中移除回收的区域

最后想给大家讲解一下G1 GC的执行过程,让大家更好的理解整个过程。


G1 包含 3 个阶段,concurrent markingOnly Young GCMixed GC。大致流程如下:

  1. Only Young GC结束时会判断是否需要开始concurrent marking
  2. concurrent marking完成后,会计算每个region(老年代)的存活对象和垃圾对象占用的space。
    1. 然后生成collection set(待回收的old region集合),只有存活对象大小占region总大小超过G1MixedGCLiveThresholdPercent的old generation region才会进入collection set.
    2. 之后,对collection set进行排序,最高的_gc_efficiency排名第一
  3. 如果collection setreclaimable_percent超过G1HeapWastePercent%,则Mixed GC稍后触发。
  4. Mixed GC 将 select 回收所有年轻区域和 old_region_length 旧区域。
    1. Mixed GC执行结束后,如果reclaimable_percent仍然超过G1HeapWastePercent%,那么稍后会再次执行Mixed GC

我来解释一下下面提到的几个参数和概念:

G1MixedGCLiveThresholdPercent

  1. openjdk11中默认值为85,G1MixedGCLiveThresholdPercent
  2. 相关使用位置为mixed_gc_live_threshold_bytes,用于计算单个区域内物体存活率的阈值。超过这个门槛的地区将不会进入collection set.

_gc_efficiency

  1. 单个区域的回收价值
  2. _gc_efficiency = the size of garbage objects in a single region / the time it takes to transfer this region
  3. 如果区域内垃圾对象越多,传送时间越短,_gc_efficiency会更高

G1HeapWastePercent

  1. openjdk11中默认值为5,G1HeapWastePercent
  2. 相关代码next_gc_should_be_mixed用于判断下一次GC是否为Mixed GC.

reclaimable_percent

  1. reclaimable_percent = garbage object size / total space size
  2. 这里的垃圾对象是指collection set
  3. 中垃圾对象的总大小

G1MixedGCCountTarget

  1. openjdk11中默认值为8,G1MixedGCCountTarget
  2. 表示一旦触发Mixed GC,期望执行8次Mixed GC。

G1OldCSetRegionThresholdPercent

  1. openjdk11中默认值为10,G1OldCSetRegionThresholdPercent
  2. 每次Mixed GC,selected old_region_length有一个最大值
  3. 最大值=the number of allocated regions in heap*10 / 100

old_region_length

  1. 这个值表示collecion setMixed GCselectsold_region_length个Old Regions要回收
  2. 这个值的下限是min_old_cset_length, and the upper limit is max_old_cset_length
  3. min_old_cset_length = the size of collection set / G1MixedGCCountTarget.
  4. max_old_cset_length = the number of allocated regions in heap * G1OldCSetRegionThresholdPercent / 100
  5. 因为G1会严格控制每个GC Pause Time,所以最后的old_region_length受到gc停顿时间的约束。但是Mixed GC会将collecion set中尽可能多的region放入old_region_length,直到回收这些region的总时间接近预估的GC Pause Time.