Nivel 3 · 30 min
Garbage Collection
La recolección de basura es la dimensión de ajuste más compleja en sistemas Java de producción. Elegir el algoritmo de GC equivocado o configurar mal los presupuestos de pausa es una fuente primaria de spikes de latencia, violaciones de SLA y cortes inesperados.
Algoritmos GC: G1GC, ZGC, Shenandoah
G1GC (por defecto desde Java 9) divide el heap en regiones de igual tamaño y colecta incrementalmente, apuntando a un objetivo de pausa configurado con -XX:MaxGCPauseMillis (por defecto 200ms). ZGC (listo para producción desde Java 15) está diseñado para pausas sub-milisegundo sin importar el tamaño del heap — usa punteros coloreados y load barriers para hacer la mayor parte del trabajo concurrentemente. Shenandoah similarmente apunta a pausas bajas con compactación concurrente. Serial GC y Parallel GC están optimizados para throughput pero tienen pausas stop-the-world proporcionales al tamaño del heap.
Análisis de logs GC y métricas clave
Habilitá el logging GC con -Xlog:gc*:file=gc.log:time,uptime en Java 9+. Métricas clave: tiempo de pausa (duración stop-the-world), tasa de asignación (MB/s), tasa de promoción (objetos moviéndose de Young a Old), ocupación del heap antes/después del GC, y throughput del GC (% de tiempo NO en GC). Un GC completo es una señal de alerta — significa que la colección concurrente no puede seguir el ritmo de la tasa de asignación.
Trade-offs throughput vs latencia
Ningún algoritmo GC te da máximo throughput y mínima latencia simultáneamente. Parallel GC maximiza el throughput (más CPU para trabajo de GC) a costa de pausas STW largas. G1GC balancea ambos con un objetivo de pausa. ZGC/Shenandoah minimizan el tiempo de pausa pero usan más CPU para trabajo concurrente, reduciendo el throughput de la aplicación ~5-15%. Las perillas clásicas de ajuste: tamaño del heap, NewRatio, y MaxGCPauseMillis.
Code example
# Logging unificado Java 9+ — esencial para diagnóstico
-Xlog:gc*:file=gc.log:time,uptime:filecount=5,filesize=20m
# G1GC con objetivo de pausa agresivo
-XX:+UseG1GC -XX:MaxGCPauseMillis=100
-XX:InitiatingHeapOccupancyPercent=35
# ZGC para ultra-baja latencia
-XX:+UseZGC -Xms4g -Xmx4g
# Shenandoah
-XX:+UseShenandoahGC
# Analizar con GCEasy o GCViewer:
# grep "Pause Full" gc.log — eventos de GC completo
# grep "to-space exhausted" gc.log — modo de fallo G1