Para configurar los parámetros JVM para minimizar las detenidas de recolección de basura (GC), es importante comprender las operaciones fundamentales de los diferentes colectores de basura y los mecanismos de sintonización disponibles en el JVM. El proceso de configuración implica seleccionar un algoritmo de recolección de basura apropiado, ajustar tamaños de montón, configurar objetivos de tiempo de pausa, roscarse parámetros y optimizar las regiones de memoria. A continuación se muestra una síntesis detallada del ajuste JVM para minimizar las pausas de GC basadas en fuentes autorizadas y las mejores prácticas:
Eligiendo el recolector de basura correcto
El JVM ofrece múltiples algoritmos de recolección de basura, cada uno con diferentes características sobre el rendimiento, los tiempos de pausa y el uso de recursos:
- Serial GC: usa un solo hilo para GC. Detiene todos los hilos de aplicación durante la recolección, lo que resulta en pausas largas. Generalmente no es adecuado para minimizar pausas en aplicaciones más grandes.
- GC paralelo: utiliza múltiples hilos para realizar la recolección de basura, reduciendo los tiempos de pausa en comparación con GC en serie aprovechando múltiples núcleos de CPU. Está orientado al rendimiento, pero aún detiene los hilos de aplicación durante GC.
- GC concurrente Mark-Sweep (CMS): realiza gran parte del trabajo de recolección de basura simultáneamente con la aplicación, reduciendo significativamente los tiempos de pausa al detener brevemente la aplicación en fases GC específicas. Es adecuado para aplicaciones de baja latencia.
- Garbage First (G1) GC: divide el montón en regiones y se enfoca en recolectar regiones con la mayor cantidad de basura primero. Su objetivo es proporcionar tiempos de pausa predecibles y un buen rendimiento mediante la mezcla de fases concurrentes y paralelas. A menudo es el valor predeterminado en las versiones JVM modernas.
- Shenandoah y ZGC: estos coleccionistas de baja latencia realizan todos o la mayoría de GC funcionan simultáneamente, apuntando a pausas muy cortas o casi imperceptibles, adecuadas para grandes montones y aplicaciones altamente receptivas.
Elegir el coleccionista correcto depende de los requisitos de aplicación, como el tiempo de pausa tolerado máximo, el tamaño del montón y las características de la carga de trabajo.
Configuración del tamaño del montón
El tamaño del montón tiene un impacto directo en la frecuencia de GC y las duraciones de la pausa:
-Establezca el tamaño inicial y máximo del montón igual: usando `-xms` y` -xmx` con el mismo valor evita el cambio de tamaño de montón, lo que puede introducir pausas durante el tiempo de ejecución.
- Tamaño adecuado del montón: el montón sub-alocador causa colecciones frecuentes, aumentando las pausas. Sin embargo, la sobre-alocación conduce a ciclos GC más largos. Encuentre un saldo basado en las necesidades de memoria de la aplicación.
- Monitoree los registros de GC y las métricas de uso del montón para ajustar el tamaño del montón de manera adecuada.
Controlar el tiempo de pausa de GC
El JVM proporciona parámetros para establecer objetivos para los tiempos máximos de pausa de GC:
- `-xx: maxgcpausemillis =`: establece un tiempo de pausa máximo objetivo en milisegundos para que el coleccionista intente cumplir. Aunque no está garantizado, el JVM intenta ajustar el rendimiento y el trabajo de GC para evitar exceder este tiempo de pausa.
- Use este parámetro con G1 GC u otros coleccionistas que admitan los objetivos de tiempo de pausa para guiar el JVM en el equilibrio de rendimiento y latencia.
roscado y paralelismo
Aprovechar múltiples hilos durante la recolección de basura reduce la duración de pausa:
- `-xx: parallelgcthreads =`: Establece el número de hilos utilizados durante las fases paralelas de GC. Más hilos pueden reducir el tiempo de pausa, pero también pueden aumentar el uso de la CPU.
- `-xx: ConcGCThreads =`: Para coleccionistas concurrentes como CMS y G1, establece el número de hilos que realizan fases concurrentes.
- El recuento óptimo de subprocesos debe alinearse con el número de núcleos de CPU disponibles y la carga de trabajo; Los hilos de suscripción excesivo pueden degradar el rendimiento.
Tanje de tamaños de generación jóvenes y antiguos
Heap típicamente se divide en generaciones jóvenes y viejos. La sintonización de sus tamaños afecta el comportamiento de GC:
- Tamaño de la generación joven: la generación joven más grande reduce la frecuencia de los GC menores, pero aumenta los tiempos de pausa de GC menores. Ajustar según la tasa de asignación de objetos.
- Tamaño de la generación anterior: afecta la frecuencia con la que se ejecutan GCS principales/completos y su duración.
- G1 GC divide el montón en muchas regiones de tamaño igualmente y administra el tamaño dinámicamente, pero permite ajustar los umbrales de inicio con parámetros como `-xx: iniciando la coincidencia de ocuoscentreno`.
Parámetros específicos del recolector de basura
Para G1 GC, comúnmente usado en JVM modernos:
- `-xx:+useG1gc`: habilita G1 GC.
- `-xx: maxgcpausemillis =`: PAUSE TIME TISTA.
- `-xx: iniciando la coincidencia de octava =`: Comienza a la marca concurrente cuando el montón alcanza esta ocupación.
- `-xx:+useStringDeduplication`: Reduce la huella de la memoria al deduplicar cadenas.
- Evite establecer explícitamente el tamaño de la generación joven, ya que puede interferir con los objetivos de tiempo de pausa de G1.
Para CMS GC:
- `-xx:+useConcmarkSweepgc`: habilita CMS.
-Centrar el enfoque en la reducción de las pausas globales de parada del mundo ajustando el umbral de iniciación y los recuentos de hilos.
Para GC paralelo (orientado al rendimiento):
-`-xx:+UseParallElgc` y` -xx:+UseParalleloldgc`: Habilita GC paralelo para generaciones jóvenes y antiguas.
- Tune Número de hilos GC con `-xx: parallelgcthreads`.
Reducción de la tasa de asignación de objetos
Reducir la velocidad a la que se crean nuevos objetos disminuye la presión de GC:
- Perfil y optimizar el código para minimizar la creación innecesaria de objetos.
- Use la agrupación de objetos y la reutilización cuando sea posible.
- Ajuste los parámetros JVM para regular las regiones de memoria interna para obtener mejores patrones de asignación de objetos.
Evite las llamadas GC explícitas
- Desactive las llamadas GC explícitas desde el código de aplicación o las herramientas externas que pueden activar las pausas de GC completas usando `-xx:+DisableExplicitGC`.
Monitoreo y registro
Para comprender y ajustar el comportamiento de GC, habilite el registro detallado de GC:
- Use `-xlog: GC*` en JVMS que admite el registro unificado (Java 9+).
-En JVM más antiguos, use `-xx:+printgcdetails -xx:+printgcDateStamps -xLogGC:`.
Analice los registros para identificar las causas de pausa y sintonice en consecuencia.
Recomendaciones generales
- Comience a ajustar con una pizarra limpia eliminando argumentos JVM obsoletos.
- Los cambios de prueba en un entorno de producción.
- Use herramientas como Java Flight Recorder, VisualVM o Profilers comerciales para recopilar datos de uso de GC y memoria.
- itera los pasos de ajuste basados en los tiempos de pausa de GC observados, el rendimiento y la capacidad de respuesta de la aplicación.
En resumen, la minimización de las pausas de recolección de basura JVM implica seleccionar el recolector de basura apropiado (preferiblemente G1, ZGC o Shenandoah para los requisitos de pausa bajos), dimensionar adecuadamente el montón y generaciones, establecer objetivos de tiempo de pausa, ajustar los hilos de concurrencia, minimizar la tasa de asignación de objetos, deshabilitar los GC explícitos y monitoreo cuidadoso. Los detalles dependerán de la carga de trabajo de la aplicación, el tamaño del montón, la versión JVM y las características de hardware. Los ajustes deben realizarse de forma incremental y validar con herramientas de monitoreo y registros de GC detallados para lograr el equilibrio deseado de rendimiento y tiempo de pausa.
Este enfoque asegura que la recolección de basura del JVM funcione de manera eficiente con interrupciones mínimas al rendimiento de la aplicación.