Introducción al proceso de reciclaje y recolección de basura G1

1. ¿Qué es G1?
Al igual que CMS, G1 también se preocupa por el tiempo de pausa, pero es controlable. Está diseñado para reemplazar a CMS. Debido a que es una organización espacial, no tiene el grave problema de fragmentación espacial de CMS, al tiempo que proporciona Tiempo de pausa controlable.

Características:
1. G1 es diferente de los recolectores de basura anteriores que se dividen en sucesivas generaciones jóvenes, generaciones viejas y generaciones permanentes, pero regiones (regiones), que dividen el montón en regiones grandes y pequeñas (generalmente alrededor de 2048). Cada área es eden, superviviente, antiguo
2. En general, dé prioridad a recuperar el área que contiene más basura, por lo que se llama Garbage-First (G1)
3. El recolector de basura anterior es la nueva generación o la generación anterior, y G1 toma en cuenta la generación joven y la generación anterior
4. Controlabilidad: Debido a que G1 puede optar por reciclar parte del área, puede lograr la controlabilidad del tiempo de pausa.Puede
ver la estructura del montón de G1, que se divide en un área.
Inserte la descripción de la imagen aquí

Varios términos introducen
conjuntos recordados : cada área tiene un RSet, que se utiliza para registrar las referencias de objeto que ingresan al bloque (por ejemplo, el objeto en el bloque A se refiere al bloque B, y el Rset del bloque B necesita registrar esta información), Puede evitar escanear toda el área, pero solo necesita escanear Rset, que se utiliza para realizar la paralelización del proceso de recolección y permitir la recolección independiente de bloques. En general, los conjuntos recordados consumen menos del 5% de la memoria.

Conjuntos de recopilación: la recopilación de regiones que se recopilarán en el GC. Las regiones de varias generaciones se pueden almacenar en CSet. Los objetos activos en CSet se moverán (copiarán) en gc. Después de GC, la región del CSet se convertirá en una partición disponible.

La máquina virtual de Card Table Java utiliza una estructura de datos llamada CardTable (tabla de tarjetas) para ** marcar si un objeto en un área de memoria determinada en la generación anterior tiene una referencia a un objeto de nueva generación, ** el número de tablas de tarjetas depende de la generación anterior El tamaño de y el tamaño de la memoria correspondiente a cada tarjeta. Cada tarjeta corresponde a un bit en la tabla de tarjetas. Cuando un objeto de la generación anterior tiene una referencia al objeto de nueva generación, la JVM coloca la tarjeta correspondiente a este objeto La ubicación se marca como sucia (el bit bit se establece en 1), de modo que en el GC menor, en lugar de escanear toda la generación anterior, escanee el área de memoria correspondiente a Sucio de tarjeta.

Región enorme: es la partición en G1 que almacena objetos enormes. Un objeto enorme se refiere a un objeto que ocupa más del 50% de la capacidad de la región. Si un área H no puede contener un objeto enorme, se almacenará a través de varias H consecutivas particiones. Debido a que la transferencia de objetos gigantes afectará la eficiencia del GC, cuando la fase de marcado concurrente descubra que los objetos gigantes ya no están vivos, se reciclarán directamente. ygc también recuperará objetos enormes en algunos casos.

Búfer de subprocesos local TLAB (búfer de asignación local de subprocesos) : dado que los objetos generalmente se asignan en el montón y el montón es compartido por subprocesos, puede haber varios subprocesos que soliciten espacio en el montón, y cada asignación de objetos debe estar sincronizada con subprocesos. la eficiencia de la distribución. Entonces, cuando se inicializa el hilo, también se aplicará a una parte de la memoria de un tamaño específico en el área de eden, que solo es utilizada por el hilo actual, de modo que cada hilo tenga un espacio separado. Si necesita asignar memoria, asignarlo en su propio espacio La ausencia de competencia puede mejorar en gran medida la eficiencia de la distribución.

Asignación en la pila : para esos objetos privados de subprocesos (objetos a los que no pueden acceder otros subprocesos), se pueden dispersar y asignar en la pila en lugar de en el montón, de modo que no se necesita GC y se destruye el subproceso. . El espacio de la pila es pequeño y es imposible asignarlo a la pila para objetos grandes. La asignación en la pila depende del análisis de escape y la sustitución escalar.

Instantánea al principio (SATB) : SATB es un algoritmo de marcado incremental utilizado en la fase de marcado simultáneo de G1 GC. SATB puede entenderse como tomar una instantánea de los objetos en la memoria del montón antes de que comience el GC. En este momento, los objetos en vivo se consideran vivos, formando así un gráfico de objetos

2. El proceso de recolección de basura de
G1 El proceso de recolección de basura de G1 puede incluir 4 partes:
1. GC cenozoico
2. Ciclo de marcado concurrente
3. Recolección mixta 4.
GC completa

1. GC Cenozoico : Al
igual que otros recolectores de basura, recupera el área del Edén, transfiere el área de supervivientes o promueve el antiguo. La diferencia es que el tamaño de la nueva generación se ajustará dinámicamente, según la información histórica de ygc y el tiempo de pausa establecido por -XX: MaxGCPauseMillis.

2. Ciclo de marcado concurrente : (algo similar al CMS) es principalmente para marcar objetos reciclables y recuperar áreas completamente libres. El proceso:

  • Marcado inicial : marcar el objeto directamente accesible desde el nodo raíz, acompañado de un ygc, STW
  • Escaneo del área de la raíz : debido a que se ha realizado ygc, solo el área de sobreviviente tiene objetos y escanea las referencias del área de sobreviviente a la generación anterior (no puede tener ygc, debe esperar al final, porque ygc hará que el área de sobreviviente cambio)
  • Marcado concurrente : escanee y encuentre los objetos supervivientes en todo el montón, y márquelos (ygc puede interrumpir el proceso de marcado)
  • Remarcado : STW, usando SATB, creará una instantánea de los objetos supervivientes al comienzo del marcado, acelerando la velocidad de re-marcado
  • Limpieza exclusiva : Calcule y clasifique los objetos supervivientes y las proporciones de recuperación en cada área, identifique las áreas disponibles para la recuperación mixta y actualice el RemeberedSet. Esta etapa marca las áreas que necesitan recuperación mixta, STW
  • Limpieza concurrente : Identifique y limpie áreas completamente libres

3. Reciclaje mixto En el
ciclo de marcado concurrente, aunque algunos objetos se reciclan, en general, la proporción de reciclaje es relativamente baja.
El reciclaje híbrido no solo realiza ygc, sino que también recicla las áreas marcadas con más basura.

4.
El GC completo activará el GC completo cuando la memoria sea insuficiente durante el proceso de recuperación mixta. ①.
Fallo del modo concurrente
②. Fallo de asignación de objetos grandes
③. Fallo de promoción

Instancia de GC Three.G1

参数设置
-Xms10M -Xmx10M -Xmn3m -XX:+PrintGCDetails -XX:+UseG1GC
 -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
import java.util.ArrayList;

public class TestCMSGC {
    private static byte[] mem = new byte[1024 * 1024 *3];
    public static void main(String[] args) {
        ArrayList<byte[]> arrayList = new ArrayList<>();
           for(;;)
           arrayList.add(mem);
    }
}

registro de ygc:

[GC pause (G1 Humongous Allocation) (young) (initial-mark), 0.0017438 secs]
   [Parallel Time: 1.5 ms, GC Workers: 6]
      [GC Worker Start (ms): Min: 104.7, Avg: 104.9, Max: 105.2, Diff: 0.4]
      [Ext Root Scanning (ms): Min: 0.4, Avg: 0.5, Max: 1.0, Diff: 0.6, Sum: 3.1]
      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Object Copy (ms): Min: 0.0, Avg: 0.7, Max: 0.9, Diff: 0.9, Sum: 4.2]
      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.2]
         [Termination Attempts: Min: 1, Avg: 45.2, Max: 101, Diff: 100, Sum: 271]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
      [GC Worker Total (ms): Min: 1.0, Avg: 1.3, Max: 1.4, Diff: 0.4, Sum: 7.6]
      [GC Worker End (ms): Min: 106.2, Avg: 106.2, Max: 106.2, Diff: 0.0]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.0 ms]
   [Other: 0.2 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.1 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.0 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]
   [Eden: 3072.0K(3072.0K)->0.0B(2048.0K) Survivors: 0.0B->1024.0K Heap: 6000.1K(10.0M)->4152.0K(10.0M)]
Parallel Time: 1.5 ms 所有GC线程的花费时间,1.6毫秒
GC Worker Start  表示这里6个GC线程启动时间
Ext Root Scanning  根扫描时间
Update RS 更新记忆集,Remembered Sets:每个区块都有一个 RSet,用于记录进入该区块的对象引用(如区块 A 中的对象引用了区块 B,区块 B 的 Rset 需要记录这个信息),可以避免扫描整个区,而只需要扫描Rset就行,它用于实现收集过程的并行化以及使得区块能进行独立收集。
Scan RS 扫描RS时间
Object Copy  在正式回收前,G1会将存活对象放在其他区域,因此需要对象复制
Termination 线程花在终止阶段的耗时,GC线程终止前,会检查还有没对象没处理完,如果没处理完,请求终止的GC线程会去帮助完成。Termination Attempts 表示每个工作线程尝试终止的次数
GC Worker Other  GC线程哈在其他任务的耗时
GC Worker Total  GC耗时
GC Worker End   单个GC线程结束的时间
Other 其他几个任务的耗时
Choose CSet  
Ref Proc  处理弱引用,软引用的时间
Ref Enq   弱引用,软引用的入队时间
Redirty Cards  重新脏化卡表
Humongous Register,Humongous Reclaim   主要是对巨型对象回收的信息,youngGC阶段会对RSet中有引用的短命的巨型对象进行回收,巨型对象会直接回收而不需要进行转移(转移代价巨大,也没必要)

Free CSet  是否被回收的Cset区域

Registro de ciclo de marcado mixto:
puede ver que el ciclo de marcado simultáneo comienza después de que se completa ygc

[Pausa de GC (Asignación enorme de G1) (joven) (marca inicial), 0,0010437 segundos]
[Tiempo paralelo: 0,8 ms, Trabajadores de GC: 6]
[Inicio de trabajador de GC (ms): Mín: 77,5, Promedio: 77,6, Máx: 77.8, Diff: 0.3]
[Ext Root Scanning (ms): Min: 0.0, Avg: 0.3, Max: 0.7, Diff: 0.7, Sum: 1.9]
[Update RS (ms): Min: 0.0, Avg: 0.0, Max : 0.0, Diferencia: 0.0, Suma: 0.0]
[Búferes procesados: Mín .: 0, Promedio: 0.0, Máx .: 0, Diferencia: 0, Suma: 0]
[Escaneo RS (ms): Mín: 0.0, Promedio: 0.0, Máx .: 0.0, Diferencia: 0.0, Suma: 0.0]
[Escaneo de raíz de código (ms): Mín .: 0.0, Promedio: 0.0, Máx .: 0.0, Diferencia: 0.0, Suma: 0.0]
[Copia de objeto (ms): Mín .: 0.0 , Promedio: 0.3, Máx .: 0.4, Diferencia: 0.4, Suma: 2.1]
[Terminación (ms): Mín: 0.0, Promedio: 0.0, Máx .: 0.0, Diferencia: 0.0, Suma: 0.2]
[Intentos de terminación: Mín .: 1, Promedio: 2.5, Máx .: 5, Diferencia: 4, Suma: 15]
[Trabajador de GC Otro (ms): Mín .: 0.0, Promedio: 0.0, Máx .: 0.0, Diferencia: 0.0, Suma: 0,2]
[Total del trabajador de GC (ms): Mín: 0,5, Promedio: 0,7, Máx .: 0,8, Diferencia: 0,3, Suma: 4,4]
[Fin del trabajador de GC (ms): Mín: 78,3, Promedio: 78,3, Máx: 78,3, Diff: 0.0]
[Code Root Fixup: 0.0 ms]
[Code Root Purge: 0.0 ms]
[Clear CT: 0.0 ms]
[Other: 0.2 ms]
[Choose CSet: 0.0 ms]
[Ref Proc: 0.1 ms]
[Ref Enq : 0.0 ms]
[Tarjetas Redirty: 0.0 ms]
[Registro gigantesco: 0.0 ms] [Recuperación gigantesca
: 0.0 ms]
[CSet libre: 0.0 ms]
[Eden: 2048.0K (3072.0K) -> 0.0B (2048.0K) Supervivientes : 0.0B-> 1024.0K Montón: 1621.2K (10.0M) -> 704.1K (10.0M)]
[Tiempos: usuario = 0.00 sys = 0.00, real = 0.00 segundos] Se
puede ver que el ciclo de marcado concurrente comienza después de que se completa el ygc anterior, seguido de escaneo de raíz, marcado concurrente, remarcado, limpieza exclusiva, limpieza concurrente
[GC concurrente -root -region-scan-start]
[GC concurrent-root-region-scan-end, 0.0003243 segs]
[GC concurrent-mark-start]
[GC concurrent-mark-end, 0.0000137 segs]
[Observación de GC [Finalizar marcado, 0.0000911 segundos] [Proc ref. GC, 0.0000384 segundos] [Descarga, 0.0005454 segundos], 0.0007483 segundos]
[Tiempos: usuario = 0.00 sys = 0.00, real = 0.00 segundos]
[Limpieza del GC 6904K-> 6904K (10M), 0.0001752 segundos ]
[Tiempos: usuario = 0.00 sys = 0.00, real = 0.00 segundos]
[GC concurrent-cleanup-start]
[GC concurrent-cleanup-end, 0.0002721]

Más registros de G1 GC pueden hacer referencia a esto:
https://www.cnblogs.com/javaadu/p/11220234.html

4. Configuración de parámetros

-XX: + UseG1GC

Usar colector G1

-XX: MaxGCPauseMillis = 200
-XX: G1MixedGCCountTarget: Después de una marca global concurrente, el número máximo de MixedGC subsiguientes ejecutados. El valor predeterminado es 8.

Especifique el tiempo de pausa objetivo, el valor predeterminado es 200 milisegundos.

Al configurar el valor -XX: MaxGCPauseMillis, no especifique el tiempo promedio, pero debe especificar que el 90% de las pausas están dentro de este tiempo. Recuerde, el objetivo del tiempo de pausa es nuestro objetivo y no siempre se cumple.

-XX: InitiatingHeapOccupancyPercent = 45

Una vez que toda la pila alcanza esta proporción, se activa el ciclo de calificación simultánea, que es del 45% por defecto.

Si desea reducir el fracaso de la promoción, generalmente puede ajustar este valor para hacer que el ciclo concurrente avance

-XX: NewRatio = n

Generación antigua / generación joven, el valor predeterminado es 2, lo que significa 1/3 de la generación joven, 2/3 de la generación anterior

No establezca la generación joven en un tamaño fijo, de lo contrario:

G1 ya no necesita cumplir con nuestro objetivo de tiempo de pausa y
ya no puede expandir o reducir el tamaño de la generación joven según sea necesario
-XX: SurvivorRatio = n

Eden / Survivor, el valor predeterminado es 8, esto es lo mismo que otros coleccionistas generacionales

-XX: MaxTenuringThreshold = n

El umbral de edad para la promoción de la generación joven a la generación anterior es el mismo que el de otros coleccionistas generacionales

-XX: ParallelGCThreads = n

Número de subprocesos de recolección de basura en recolección paralela

-XX: ConcGCThreads = n

El número de subprocesos de recolección de basura en la fase de marcado concurrente

El aumento de este valor puede hacer que el marcado simultáneo se complete más rápido. Si no se especifica este valor, la JVM se calculará mediante la siguiente fórmula:

ConcGCThreads = (ParallelGCThreads + 2) / 4 ^ 3

-XX: G1ReservePercent = n

El porcentaje del espacio reservado de la memoria del montón, el valor predeterminado es 10, para reducir el riesgo de error de promoción, es decir, el 10% de la memoria del montón está reservado de forma predeterminada.

-XX: G1HeapRegionSize = n

El tamaño de cada región, el valor predeterminado se calcula de acuerdo con el tamaño del montón, el valor es de 1 MB ~ 32 MB, generalmente especificamos el tamaño completo del montón.
-XX: G1MixedGCCountTarget El
número máximo de ejecuciones de MixedGC subsiguientes después de una marca simultánea global. El valor predeterminado es 8.

Referencia:
https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html
https://javadoop.com/post/g1
https://www.jianshu.com/p/9edcbc4bcb8b?from=singlemessage
https : //blog.csdn.net/lijingyao8206/article/details/80566384
https://blog.csdn.net/lijingyao8206/article/details/80513383
https://ezlippi.com/blog/2018/01/jvm-card -table-turn.html

Supongo que te gusta

Origin blog.csdn.net/u010857795/article/details/112972045
Recomendado
Clasificación