Post on 09-Jul-2015
description
JVM GCWTF?!
Alonso Torres @alotor
Alonso Torres
@alotor @alotor
mobro.co/alotor
java.lang.OutOfMemoryError: unable to create new native thread
java.lang.OutOfMemoryError: Stack overflow
java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: Metaspace
java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: GC overhead limit exceeded
java.lang.OutOfMemoryError: requested... Out of swap space?
SUCCESS
No tengo memoria!!!
Todo va lento!!!!!!
El GC es ineficiente!!!!!
With CMS GC, the full collection is serial and STW, hence your application threads are stopped for the entire duration while the heap space is reclaimed and then compacted.
The duration for the STW pause depends on your heap size and the surviving objects.
http://www.infoq.com/articles/G1-One-Garbage-Collector-To-Rule-Them-All
Con el recolector CMS, la recolección es “serie” y STW, y los hilos de tu aplicación serán detenidos por la duración completa mientras el espacio del “heap” es recuperado y compactado.
La duración de la pausa STW dependerá del tamaño del “heap” y de los objetos supervivientes.
http://www.infoq.com/articles/G1-One-Garbage-Collector-To-Rule-Them-All
JVMJava Virtual Machine
GCGarbage Collectors
WTF?!Why They Fail?!
1. Estructura de la memoria
2. Conceptos generales de GC
3. Tipos de recolectores de Hotspot
4. Configuración de Hotspot
Os presento la
JVM
JVM PROCESS: 1.591 Gb
JVM PROCESS: 1.591 Gb
Memoria propia de la JVM
JVM PROCESS: 1.591 Gb
Memoria de ejecución
JVM PROCESS: 1.591 Gb
Memoria de datos
JVM PROCESS: 1.591 Gb
Memoria de clases
HEAP
- Bloque de memoria que la JVM se encargará de gestionar
- Almacena los datos de los objetos
- Memoria dinámica
LIBREOCUPADA
Max. Heap Size
LIBREOCUPADA
Max. Heap Size
LIBREOCUPADA
Max. Heap Size
LIBREOCUPADA
LIBREOCUPADA
AUMENTAMOS el heap
ó
LIBERAMOS memoria
OCUPADA LIBRE
OCUPADA LIBRE
Aumenta el heap
Liberamos el heap
¿Cómo liberamos la memoriaque ya no necesitamos?
1. Busca todos los objetos vivos
2. Libera la memoria de los objetos muertos
3. Mueve la posición de memoria de los vivos
Garbage Collection
- Serial Collector
- Parallel Collector
- CMS Collector
- G1
GC’s en OpenJDK Hotspot
- Serial Collector
- Parallel Collector
- CMS Collector
- G1
GC’s en OpenJDK Hotspot
MALDITOS TÉRMINOS!!
- Parada global de todos los hilos de ejecución para realizar recolección de basura
- El contrario puede ser CONCURRENTE○ La recolección se ejecuta a la vez que el
programa
Stop the World (STW)
STW Concurrente
● La ejecución se realiza en varios hilos de ejecución
● Aprovecha sistemas con múltiples CPUs
● Por contra puede ser SERIE○ Sólo se ejecutaría en un hilo
Paralelo
Paralelo Serie
● El trabajo de recolección no se realiza en un único paso sino en varias fases o pasos
● Por el contrario puede ser MONOLÍTICO○ Todo se ejecuta en un sólo paso
Incremental
Incremental Monolítico
- La mayoría de los objetos mueren jóvenes
- Los objetos viejos no suelen referenciar a objetos jóvenes
Weak Generational Hypothesis
Dos tipos de recolección:
○ 1 espacio pequeño con muchos muertos
○ 1 espacio grande donde casi todos vivos
Generational GC
Núm
ero
de o
bjet
os v
ivos
Número de objetos
TODOSlos GC’s son generacionales
YOUNG OLD/TENURE
Generational heap structure
SURVIVORS
OLD/TENUREEDEN
Generational heap structure
SURVIVORS
Recolectamos la Young Generation
Objetos promocionados van a supervivientes y a la Old Generation
La Old Generation está llena
Necesitamos una recolección completa
Empty young and survivors.
Free dead old-gen objects
● Serial Collector
● Parallel Collector
● CMS Collector
● G1 (Garbage First) Collector
GC’s en OpenJDK Hotspot
YOUNG GENERATION OLD GENERATION
Serial
Monolithic
Stop-The-World
Copying Mark / Sweep / Compact
Serial Collector
- Copia los objetos vivos de una región de la memoria a otra
- Libera la zona de memoria antigua
Algoritmo de COPIA (Scavenge)
Mark / Sweep / Compact (MSC)
1. Mark
2. Sweep
Mark / Sweep / Compact (MSC)
3. Compact
Mark / Sweep / Compact (MSC)
● Serial Collector
● Parallel Collector
● CMS Collector
● G1 (Garbage First) Collector
GC’s en OpenJDK Hotspot
Parallel Collector
YOUNG GENERATION OLD GENERATION
Paralelo Serie / Paralelo
Monolítico
Stop-The-World
Copying Mark / Sweep / Compact
● Serial Collector
● Parallel Collector
● CMS Collector
● G1 (Garbage First) Collector
GC’s en OpenJDK Hotspot
YOUNG GENERATION OLD GENERATION
Paralelo Serie Y Paralelo
Monolítico Incremental
Stop-The-World STW Y Concurrente
Copying Mark and Sweep
Concurrent Mark & Sweep
1. Initial Mark
2. Concurrent Mark
3. Remark
4. Concurrent Sweep
Concurrent Mark & Sweep
CMSNo compacta
CMS después de varias generaciones
Cuando hay excesiva
fragmentación
STW,Serial, Monolithic, MSC*
*AKA: Full GC
● Serial Collector
● Parallel Collector
● CMS Collector
● G1 (Garbage First) Collector
GC’s en OpenJDK Hotspot
- Retrasar al máximo un “Full GC”
- Baja latencia
- Predictibilidad
- Fácil de usar
Garbage First (G1)
- Divide el heap en regiones
- Libera primero las que tienen más basura (Garbage First)
- Compacta sobre la marcha
Garbage First (G1)
E O
O
E
O
O
O
S
G1 Heap Structure
E
1. Recolección de Young Collection
2. Marcado concurrente
3. Recolección mixta
4. Full GC
Garbage First (G1)
Young collection
E O
O
E E
O
O
O
E
Young collection
O
O
O
O
O
S
1. Recolección de Young Collection
2. Marcado concurrente
3. Recolección mixta
4. Full GC
Garbage First (G1)
Marcado concurrente
E O
O
O
O
O
E
O
O O
E S
Marcado concurrente
E O
O
E
X
O
X
O
O O
O
1. Recolección de Young Collection
2. Marcado concurrente
3. Recolección mixta
4. Full GC
Garbage First (G1)
Recolección mixta
E O
O
E
E X
O
X
E
O
O O
O
O
O
O
O
Recolección mixta
E O
O
E
E X
O
X
E
O
O O
O
O
O
O
O
Recolección mixta
O
O
O
X
O
O O
O
O
O
O
OS
1. Recolección de Young Collection
2. Marcado concurrente
3. Recolección mixta
4. Full GC
Garbage First (G1)
Todos los GC’s de Hotspottienen algún tipo de STW
STWes el mayor enemigo
del rendimiento
1. Maximizar recolección JOVEN
2. Minimizar los STW
3. Evitar objetos grandes
4. Evitar retención de objetos
Objetivos de optimización
Monitorizar la aplicación
-Xloggc:<file>
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
Opciones de monitorización
[GC [PSYoungGen: 578424K->8793K(630784K)]
1007570K->444386K(1155072K), 0.0185270 secs]
[Times: user=0.06 sys=0.00, real=0.02 secs]
[GC [PSYoungGen: 580697K->15128K(636928K)]
1016290K->459169K(1161216K), 0.0236090 secs]
[Times: user=0.08 sys=0.01, real=0.02 secs]
[GC [PSYoungGen: 450179K->6893K(635904K)]
894221K->465458K(1160192K), 0.0249430 secs]
[Times: user=0.07 sys=0.02, real=0.02 secs]
[Full GC [PSYoungGen: 6893K->0K(635904K)]
[ParOldGen: 458564K->454236K(816128K)] 465458K->454236K(1452032K)
[PSPermGen: 171991K->171852K(344064K)], 2.5341620 secs]
[Times: user=8.48 sys=0.01, real=2.53 secs]
[GC [PSYoungGen: 578424K->8793K(630784K)]
1007570K->444386K(1155072K), 0.0185270 secs]
[Times: user=0.06 sys=0.00, real=0.02 secs]
[GC [PSYoungGen: 580697K->15128K(636928K)]
1016290K->459169K(1161216K), 0.0236090 secs]
[Times: user=0.08 sys=0.01, real=0.02 secs]
[GC [PSYoungGen: 450179K->6893K(635904K)]
894221K->465458K(1160192K), 0.0249430 secs]
[Times: user=0.07 sys=0.02, real=0.02 secs]
[Full GC [PSYoungGen: 6893K->0K(635904K)]
[ParOldGen: 458564K->454236K(816128K)] 465458K->454236K(1452032K)
[PSPermGen: 171991K->171852K(344064K)], 2.5341620 secs]
[Times: user=8.48 sys=0.01, real=2.53 secs]
Recolección Young Generation
Full GC (STW)
YOUNG SURVIVORS OLD
Resumen del total
Análisis en detalle
jcmd pid GC.class_histogram
Herramientas
num #instances #bytes class name---------------------------------------------- 1: 762525 71798392 [C 2: 41739 68376080 [B 3: 675097 54007760 java.lang.reflect.Method 4: 404377 51770560 <methodKlass> 5: 404377 49495808 <constMethodKlass> 6: 864167 48393352 org.codehaus.groovy.runtime.metaclass. 7: 17110 29966392 <constantPoolKlass> 8: 710424 22733568 java.util.HashMap$Entry 9: 13777 18368640 <constantPoolCacheKlass> 10: 760859 18260616 java.lang.String 11: 507462 15419000 [Ljava.lang.Object; 12: 17104 14833688 <instanceKlassKlass> 13: 85375 12536048 [Lorg.codehaus.groovy.util.ComplexKeyHashMap$En 14: 303170 9701440 org.codehaus.groovy.util.SingleKeyHashMap$Entry 15: 386458 9274992 org.codehaus.groovy.util.FastArray 16: 50174 8596088 [Ljava.util.HashMap$Entry; 17: 333114 7010016 [Ljava.lang.Class;
jcmd pid GC.class_histogram
jcmd pid GC.heap_dump filename +jhat heapdumpfile
Herramientas
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=path
Herramientas
Configurar la JVM
-Xmx / -XmsTamaño máximo y mínimo del HEAP
-XX:MaxGCPauseMillis=nRecomendación de pausas
-XX:SurvivorRatio=nTamaño del espacio de supervivientes
Configuraciones
Tantas como para otra charla ;)
1. Estructura de la memoria
2. Conceptos generales de GC
3. Tipos de recolectores de Hotspot
4. Configuración de Hotspot
Con el recolector CMS, la recolección es “serie” y STW, y los hilos de tu aplicación serán detenidos por la duración completa mientras el espacio del “heap” es recuperado y compactado.
La duración de la pausa STW dependerá del tamaño del “heap” y de los objetos supervivientes.
http://www.infoq.com/articles/G1-One-Garbage-Collector-To-Rule-Them-All
No es tan fiero el lobo como lo pintan
Alonso Torres
@alotor @alotor
mobro.co/alotor
Bonus (post-presentación)
- Alternativas a JConsole○ VisualVM○ AppDynamics
- Para medir paradas del GC○ JHiccup http://www.azulsystems.com/product/jHiccup○ JMeter