Recolección de basura y documentación de Java 7 (JDK 7) en G1

82

Java 7 ha estado disponible por un tiempo, pero no puedo encontrar buenos recursos sobre la configuración de los recolectores de basura , específicamente el nuevo recolector G1 .

Mis preguntas:

  1. ¿Es G1 el recopilador predeterminado en Java 7 y si no, cómo activo G1?
  2. ¿Qué configuraciones opcionales tiene g1 en Java7?
  3. ¿Se realizaron cambios en otros colectores como cms o el colector paralelo en Java 7?
  4. ¿Dónde puedo encontrar buena documentación sobre la recolección de basura en Java 7?
Florakel
fuente
6
Comenzar con el recolector de basura G1 también brinda una buena descripción general con las mejores prácticas.
John McCarthy

Respuestas:

47

El recolector de basura G1 no es el predeterminado en mi instalación de Java, versión 1.7.0_01. Puede verlo usted mismo usando algunas opciones de línea de comando adicionales:

> java -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -version
-XX:InitialHeapSize=132304640 -XX:MaxHeapSize=2116874240 -XX:ParallelGCThreads=4 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)
Heap
 PSYoungGen      total 37696K, used 1293K [0x00000007d5eb0000, 0x00000007d88c0000, 0x0000000800000000)
  eden space 32320K, 4% used [0x00000007d5eb0000,0x00000007d5ff3408,0x00000007d7e40000)
  from space 5376K, 0% used [0x00000007d8380000,0x00000007d8380000,0x00000007d88c0000)
  to   space 5376K, 0% used [0x00000007d7e40000,0x00000007d7e40000,0x00000007d8380000)
 PSOldGen        total 86144K, used 0K [0x0000000781c00000, 0x0000000787020000, 0x00000007d5eb0000)
  object space 86144K, 0% used [0x0000000781c00000,0x0000000781c00000,0x0000000787020000)
 PSPermGen       total 21248K, used 2032K [0x000000077ca00000, 0x000000077dec0000, 0x0000000781c00000)
  object space 21248K, 9% used [0x000000077ca00000,0x000000077cbfc288,0x000000077dec0000)

Sin embargo, ya no es necesario habilitar las opciones experimentales para activar el colector G1:

> java -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseG1GC -version
-XX:InitialHeapSize=132304640 -XX:MaxHeapSize=2116874240 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedOops -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)
Heap
 garbage-first heap   total 130048K, used 0K [0x000000077ca00000, 0x0000000784900000, 0x00000007fae00000)
  region size 1024K, 1 young (1024K), 0 survivors (0K)
 compacting perm gen  total 20480K, used 2032K [0x00000007fae00000, 0x00000007fc200000, 0x0000000800000000)
   the space 20480K,   9% used [0x00000007fae00000, 0x00000007faffc288, 0x00000007faffc400, 0x00000007fc200000)
No shared spaces configured.

No sé dónde puede encontrar una buena documentación.

Carey
fuente
2
Esto sigue siendo válido para 1.7.0_09 en OSX
Age Mooij
1
Lo mismo en 1.7.0_10 en Linux
Marc Polizzi
No es cierto para Oracle JDK 7u17 en linux / amd64 obtenido directamente del sitio web de Oracle. Dice -XX:+UseParallelGC.
user1050755
31

Oracle finalmente hizo oficial G1 en Java 7 U4: http://www.oracle.com/technetwork/java/javase/7u4-relnotes-1575007.html

Descripción: http://docs.oracle.com/javase/7/docs/technotes/guides/vm/G1.html

Opciones de la línea de comandos: http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#G1Options

Aún así, no creo que sea el recopilador predeterminado en Java 7. Para los servidores, el predeterminado es Parallel Collector como en Java 6.

Florakel
fuente
1
y el servidor está definido por 2 núcleos y 2 GB de RAM o más. Los detalles se pueden encontrar a través de hg.openjdk.java.net/jdk7u/jdk7u/hotspot/file/0d82bf449a61/src - mire los archivos ./share/tools/launcher/java.cy ./share/vm/runtime/ os.cpp
user1050755
22

Sí, G1 es el nuevo recolector de basura estándar en Java 1.7 JVM.

Aquí puede encontrar mucha información sobre cómo usar y configurar el nuevo recolector de basura:

El uso de G1 G1 todavía se considera experimental y se puede habilitar con los siguientes dos parámetros:

-XX: + UnlockExperimentalVMOptions -XX: + UseG1GC

Para establecer un objetivo de tiempo de pausa de GC, use el siguiente parámetro:

-XX: MaxGCPauseMillis = 50 (para un objetivo de tiempo de pausa de 50 ms)

Con G1, se puede especificar un intervalo de tiempo durante el cual una pausa de GC no debe durar más que el tiempo indicado anteriormente:

-XX: GCPauseIntervalMillis = 200 (para un objetivo de intervalo de pausa de 200 ms)

Tenga en cuenta que las dos opciones anteriores representan objetivos, no promesas ni garantías. Es posible que funcionen bien en algunas situaciones pero no en otras, y es posible que el CG no siempre pueda obedecerlos.

Alternativamente, el tamaño de la generación joven se puede especificar explícitamente para afectar los tiempos de pausa de evacuación:

-XX: + G1YoungGenSize = 512 m (para una generación joven de 512 megabytes)

G1 también utiliza el equivalente de los espacios de supervivientes, que son, naturalmente, un conjunto de regiones (potencialmente no contiguas). Su tamaño se puede especificar con los parámetros habituales (por ejemplo, -XX: SurvivorRatio = 6).

Finalmente, para ejecutar G1 en todo su potencial, intente configurar estos dos parámetros que actualmente están deshabilitados de forma predeterminada porque pueden descubrir una condición de carrera poco común:

-XX: + G1ParallelRSetUpdatingEnabled -XX: + G1ParallelRSetScanningEnabled

Una cosa más a tener en cuenta es que G1 es muy detallado en comparación con otros HotSpot GC cuando se establece -XX: + PrintGCDetails. Esto se debe a que imprime tiempos por subproceso GC y otra información muy útil para la creación de perfiles y la resolución de problemas. Si desea un registro de GC más conciso, cambie al uso de -verbosegc (aunque se recomienda obtener el registro de GC más detallado).

También he encontrado este artículo muy útil para comprender los aspectos internos de G1.

Incluso más información aquí .

Wojtek Owczarczyk
fuente
6
He visto estos recursos. Pero el primer artículo trata sobre G1 en JDK 6 cuando todavía era una opción experimental. Los otros artículos tratan sobre las versiones beta del JDK 7 y tienen al menos 1 año de antigüedad. Estoy buscando información más actualizada o documentación oficial de Oracle o del equipo JDK.
Florakel
13

1. ¿Es G1 el recopilador predeterminado en Java 7 (...)

La regla en esta página de Java 5 todavía es aplicable en Java 7 (y AFAIK, Java 8):

En las máquinas de clase servidor que ejecutan la VM del servidor, el recolector de basura (GC) ha cambiado del recolector en serie anterior (-XX: + UseSerialGC) a un recolector paralelo (-XX: + UseParallelGC).

Pero también considere:

  • Las JVM de 64 bits no vienen con una -clientVM, por lo que siempre son de "clase de servidor"
  • Desde Java 7, el uso de -XX: + UseParallelGC (ya sea establecido o implícito) implica adicionalmente -XX: + UseParallelOldGC (es decir, a menos que esté explícitamente deshabilitado)

Por ejemplo, si en Windows x64 ejecuta ...

  • Java 7 de 64 bits, obtiene Parallel GC (para generaciones jóvenes y mayores) de forma predeterminada.
  • Java 8 de 32 bits, obtienes Serial GC (para ambas generaciones) de forma predeterminada

1. (...) ¿cómo activo G1?

A partir de Java 7, simplemente -XX:+UseG1GC. Quizás también sea de interés cuándo desearía:

Las aplicaciones que se ejecutan hoy en día con el CMS o el recolector de basura ParallelOld se beneficiarían de cambiar a G1 si la aplicación tiene una o más de las siguientes características.

  • Más del 50% del montón de Java está ocupado con datos en vivo.
  • La tasa de promoción o asignación de objetos varía significativamente.
  • Pausas prolongadas no deseadas de recolección de basura o compactación (más de 0,5 a 1 segundo)

2. ¿Qué configuraciones opcionales tiene g1 en Java7?

Yo no he usado G1, pero deduzco que se adhiere a los mismos indicadores básicos de "rendimiento / ergonomía" que se usan para sintonizar los otros colectores paralelos. En mi experiencia con Parallel GC, -XX:GCTimeRatioha sido fundamental para proporcionar el equilibrio esperado entre velocidad y memoria. YMMV.

Las opciones específicas de G1 se enumeran aquí

3. ¿Hubo cambios en (...) cms o el colector paralelo en Java 7?

No lo sé, pero ...

G1 está planeado como el reemplazo a largo plazo del colector de barrido de marcas concurrentes (CMS)

4. ¿Dónde puedo encontrar buena documentación sobre la recolección de basura en Java 7?

Puede ser doloroso encontrarlo, ¿no? Probablemente, la mejor página "central" que he encontrado es esta:

http://www.oracle.com/technetwork/java/javase/tech/index-jsp-140228.html

Se requiere algo de lectura profunda, pero vale la pena el tiempo si necesita hacer algunos ajustes. Particularmente revelador es: Ergonomía del recolector de basura

Luke Usherwood
fuente
13
  1. ¿Es G1 el recopilador predeterminado en Java 7 y si no, cómo activo G1?

G1 no es el recopilador predeterminado en Java 7. -XX:+UseG1GChabilitará G1GC

  1. ¿Qué configuraciones opcionales tiene g1 en Java7?

Hay muchos. Eche un vistazo a este artículo de Oracle para obtener información completa.

El G1 GC es un recolector de basura adaptable con valores predeterminados que le permiten funcionar de manera eficiente sin modificaciones.

Por esta razón, personalice los parámetros críticos

-XX:MaxGCPauseMillis
-XX:G1HeapRegionSize
-XX:ParallelGCThreads
-XX:ConcGCThreads

y deje todos los demás parámetros al valor predeterminado .

A continuación, se muestra una lista de opciones importantes y sus valores predeterminados. Esta lista se aplica a la última máquina virtual Java HotSpot, compilación 24. Puede adaptar y ajustar la configuración de G1 GC en la línea de comandos de JVM.

Valores predeterminados importantes:

-XX:G1HeapRegionSize=n

Establece el tamaño de una región G1. El valor será una potencia de dos y puede oscilar entre 1 MB y 32 MB. El objetivo es tener alrededor de 2048 regiones basadas en el tamaño mínimo del montón de Java.

-XX:MaxGCPauseMillis=200

Establece un valor objetivo para el tiempo máximo de pausa deseado. El valor predeterminado es 200 milisegundos. El valor especificado no se adapta a su tamaño de pila.

-XX:G1NewSizePercent=5

Establece el porcentaje del montón que se utilizará como mínimo para el tamaño de la generación joven. El valor predeterminado es el 5 por ciento de su montón de Java.

-XX:G1MaxNewSizePercent=60

Establece el porcentaje del tamaño del montón que se utilizará como máximo para el tamaño de la generación joven. El valor predeterminado es el 60 por ciento de su montón de Java.

-XX:ParallelGCThreads=n

Establece el valor de los subprocesos de trabajo STW. Establece el valor de n en el número de procesadores lógicos. El valor de n es el mismo que el número de procesadores lógicos hasta un valor de 8.

Si hay más de ocho procesadores lógicos, establece el valor de n en aproximadamente 5/8 de los procesadores lógicos. Esto funciona en la mayoría de los casos excepto en sistemas SPARC más grandes donde el valor de n puede ser aproximadamente 5/16 de los procesadores lógicos.

-XX:ConcGCThreads=n

Establece el número de hilos de marcado paralelos. Establece n en aproximadamente 1/4 del número de subprocesos de recolección de basura paralelos (ParallelGCThreads).

-XX:InitiatingHeapOccupancyPercent=45

Establece el umbral de ocupación del montón de Java que activa un ciclo de marcado. La ocupación predeterminada es el 45 por ciento de todo el montón de Java.

-XX:G1MixedGCLiveThresholdPercent=65

Establece el umbral de ocupación para que una región antigua se incluya en un ciclo de recolección de basura mixta. La ocupación predeterminada es del 65 por ciento

-XX:G1HeapWastePercent=10

Establece el porcentaje de montón que está dispuesto a desperdiciar. La máquina virtual Java HotSpot no inicia el ciclo de recolección de basura mixta cuando el porcentaje recuperable es menor que el porcentaje de desperdicio de pila

-XX:G1MixedGCCountTarget=8

Establece el número objetivo de recolecciones de basura mixtas después de un ciclo de marcado para recolectar regiones antiguas con como máximo G1MixedGCLIveThresholdPercent datos en vivo. El valor predeterminado es 8 recolecciones de basura mixtas

-XX:G1OldCSetRegionThresholdPercent=10

Establece un límite superior en la cantidad de regiones antiguas que se recopilarán durante un ciclo de recolección de basura mixta. El valor predeterminado es el 10 por ciento del montón de Java

-XX:G1ReservePercent=10

Establece el porcentaje de memoria de reserva que se debe mantener libre para reducir el riesgo de desbordamientos de espacio. El valor predeterminado es el 10 por ciento. Cuando aumente o disminuya el porcentaje, asegúrese de ajustar el montón de Java total en la misma cantidad.

Ha vuelto a configurar muchos parámetros de G1GC, que no son necesarios si sigue la página de documentación anterior. Verifique las recomendaciones anteriores, especialmente en ParallelGCThreads y ConcGCThreads , que se basarán en los núcleos de su CPU. Elimine la reconfiguración de los parámetros innecesarios.

Recomendaciones de Oracle:

Cuando evalúe y ajuste G1 GC, tenga en cuenta las siguientes recomendaciones:

  1. Tamaño de la generación joven : Evite establecer explícitamente el tamaño de la generación joven con la -Xmnopción o cualquier otra opción relacionada, como -XX:NewRatio. La fijación del tamaño de la generación joven anula el objetivo de tiempo de pausa .

  2. Objetivos de tiempo de pausa: cuando evalúa o ajusta cualquier recolección de basura, siempre existe una compensación entre latencia y rendimiento. El G1 GC es un recolector de basura incremental con pausas uniformes, pero también más sobrecarga en los subprocesos de la aplicación. El objetivo de rendimiento del G1 GC es el 90 por ciento del tiempo de aplicación y el 10 por ciento del tiempo de recolección de basura .

  1. ¿Se realizaron cambios en otros colectores como cms o el colector paralelo en Java 7?

Hay algunos cambios con Java 7. Eche un vistazo a este artículo.

  1. ¿Dónde puedo encontrar buena documentación sobre la recolección de basura en Java 7?

Consulte la página de documentación de Oracle sobre gc y la pregunta SE relacionada:

Recolección de basura Java G1 en producción

Ravindra babu
fuente
3

No G1 no es el recolector de basura predeterminado en jdk 1.7.0_02. El recolector de basura predeterminado depende de la clase de máquina. Si la máquina es de la clase Server, el recolector de basura predeterminado es Throughput Collector. Si la máquina es de la clase Client, el recolector de basura predeterminado es Serial Collector.

Nitan S. Kotwal
fuente
1
Confieso que esto es completamente correcto. Referencia de Java 5 , aún válida. En un sistema Windows (32/64): Ejecute Java de 32 bits (5..8) >> Serial GC de forma predeterminada. Ejecute Java de 64 bits (5..6) >> ParallelGC (solo generación joven) de forma predeterminada. Ejecute Java de 64 bits (7..8) >> ParallelOldGC (paralelo Young y Old) de forma predeterminada. Referencia para el cambio de Java 7 , finalmente colector 'paralelo' == colector 'rendimiento' "
Luke Usherwood
3
(Una respuesta dura por la primera y precisa contribución SO de esta persona. Observo que también es la última.)
Luke Usherwood
2

La documentación disponible en http://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html (el enlace proporcionado por Wojtek) parece ser el único enlace oficial con información pero la información parece desactualizado ya que algunas de las banderas mencionadas solo estaban disponibles en las versiones de prueba, ya no existen en las versiones de producción. Alguien de Oracle debería proporcionar documentación actualizada sobre el G1 GC.

Repartidor de hielo
fuente
0

Por defecto, realmente no desea utilizar el recopilador G1, ya que no es realmente mejor que los demás. Solo es bueno para propósitos especiales.

En aplicaciones de baja latencia, es un poco mejor que CMS, ya que tiene tiempos de pausa un poco más cortos y predecibles. A cambio, el rendimiento es mucho peor que CMS a cambio.

Por lo tanto, solo es bueno si la latencia es importante, pero el rendimiento no es importante en absoluto. Si ambos son importantes, quédese con CMS.

Zoltan Juhasz
fuente