Configuración de parámetros comunes de JVM y optimización del rendimiento de GC

Configuración de parámetros comunes de JVM

Estadísticas de recolección de basura

-XX:+PrintGC Imprime información breve del GC
-XX:+PrintGCDetails imprime información detallada del GC
-XX:+PrintGCTimeStamps imprime la marca de tiempo de la aparición del GC
-Xloggc:log/gc.log Especifica la ubicación del registro del GC y lo envía como un archivo
-XX: +PrintHeapAtGC Imprime la información del montón antes y después de cada GC.

configuración del montón

-Xms: tamaño de almacenamiento dinámico inicial, almacenamiento dinámico mínimo
-Xmx: tamaño máximo de almacenamiento dinámico
-Xmn: establece el tamaño de la nueva generación
-XX: NewRatio La relación entre la nueva generación y la generación anterior, si es 3, significa la relación de la generación joven a la generación anterior es 1 : 3, la generación joven representa 1/4 de la suma de toda la generación joven y la generación anterior
-XX: SurvivorRatio establece la proporción de las dos áreas Survivor a eden. Tenga en cuenta que hay dos áreas de Supervivientes. Por ejemplo: 8, significa Eden: Survivor=8:2, un área de Survivor ocupa 1/10 de toda la generación joven
-XX:PermSize: establece el espacio inicial del área permanente
-XX:MaxPermSize: establece el espacio máximo del área permanente.
-XX:+MaxTenuringThreshold=10: La antigüedad máxima de la nueva generación de basura, lo que significa que el objeto entra en la antigüedad después de 10 copias en el área Superviviente. Si se establece en 0, los objetos de la generación joven ingresan directamente a la generación anterior sin pasar por el área Superviviente.
-XX:+PretenureSizeThreshold: establece el umbral para que los objetos grandes ingresen directamente a la vejez. Cuando el tamaño del objeto supere este valor, se asignará directamente en la generación anterior. 

parámetros de asignación de pila

-Xss: establece el tamaño del espacio de pila

Configuración del recolector de basura

Configuraciones para el colector en serie

-XX:+UseSerialGC: Configure el colector en serie, que generalmente es adecuado para aplicaciones pequeñas y procesadores únicos. El algoritmo es relativamente simple y la eficiencia del GC es alta, pero puede provocar pausas en la aplicación.

Configuración del recopilador de recopilación paralela (el objetivo del recopilador ParallelGC es lograr un rendimiento manejable)

-XX:+UseParNewGC: Establecer generación joven para recolección paralela.
-XX:+UseParallelGC: Configure a la generación joven para que use el recopilador de recopilación paralela. Múltiples subprocesos ejecutan GC en paralelo, lo que generalmente se aplica a sistemas multiprocesador y puede mejorar la eficiencia de GC, pero el algoritmo es complejo y el sistema consume mucho.
-XX:+UseParalledlOldGC: establece la generación anterior como un recolector de reciclaje paralelo, que solo apareció después de Java1.6.
-XX:ParallelGCThreads=n: establezca la cantidad de subprocesos utilizados por el recopilador paralelo para recopilar, preferiblemente igual a la cantidad de CPU.
-XX:MaxGCPauseMillis=n: establezca el tiempo de pausa máximo para cada recolección de basura paralela de la generación joven.
-XX:GCTimeRatio=n: establece el porcentaje de tiempo de recolección de elementos no utilizados para el tiempo de ejecución del programa. La fórmula es 1/(1+n)
-XX:+UseAdaptiveSizePolicy: Política adaptativa, que selecciona automáticamente el tamaño del área de generación joven y la proporción correspondiente del área Superviviente.

Recopilador simultáneo de CMS (con la pausa más corta como objetivo)

-XX:+UseConcMarkSweepGC: Usar colección de memoria CMS.
-XX:+ParallelCMSThreads: establezca el número de subprocesos CMS. 
-XX:CMSFullGCsBeforeCompaction: después de cuántas veces CMS realiza la compresión de la memoria, dado que el recopilador concurrente no comprime ni organiza el espacio de la memoria, se generará una "fragmentación" después de ejecutarse durante un período de tiempo, lo que reduce la eficiencia operativa.
-XX:+UseCMSCompactAtFullCollection: Compresión de la generación anterior durante FULL GC. CMS no mueve la memoria, por lo que es muy propensa a la fragmentación, lo que resulta en memoria insuficiente, por lo que la compresión de memoria estará habilitada en este momento. Puede afectar el rendimiento, pero elimina la fragmentación.
-XX:+CMSInitiatingOccupancyFraction: Configure el recopilador de CMS para que se active después de que se use el espacio de antigüedad, el valor predeterminado es 68 %. 
-XX:+CMSClassUnloadingEnabled: permite el reciclaje de metadatos de clase.
-XX:+CMSParallelRemarkEndable: Habilitar comentario paralelo. 
-XX:CMSInitatingPermOccupancyFraction: cuando la ocupación del área permanente alcance este porcentaje, inicie la recuperación de CMS (siempre que -XX:+CMSClassUnloadingEnabled esté activado). 
-XX:UseCMSInitatingOccupancyOnly: Indica que el reciclaje de CMS solo se realizará cuando se alcance el umbral. 
-XX:+CMSIncrementalMode: use el modo incremental, que es más adecuado para una sola CPU. 

colector G1

-XX:+UseG1GC: Usa el colector G1. 
-XX:+DesbloquearExperimentalVMOptions: Permitir parámetros experimentales. 
-XX:+MaxGCPauseMills: establece el tiempo máximo de pausa de recolección de basura. 
-XX:+GCPauseIntervalMills: establece el intervalo de pausa. 

Optimización del rendimiento de GC de JVM

Existen principalmente dos indicadores para el rendimiento de GC: rendimiento (no se cuenta el tiempo de trabajo, la relación entre el tiempo de gc y el tiempo total) y el tiempo de pausa.

tamano de la pila

De forma predeterminada, la máquina virtual aumentará o disminuirá el tamaño del almacenamiento dinámico para mantener la proporción de espacio libre en toda la máquina virtual, que se especifica en MinHeapFreeRatio y MaxHeapFreeRatio.

En términos generales, la aplicación del lado del servidor tendrá las siguientes reglas:

(1) Asigne tanta memoria como sea posible a vm;
(2) Establezca Xms y Xmx en el mismo valor. Si la memoria utilizada por la máquina virtual es relativamente pequeña cuando se inicia y es necesario inicializar muchos objetos en este momento, la máquina virtual debe aumentar la memoria repetidamente.
(3) A medida que aumenta la cantidad de núcleos de procesador, también aumenta la memoria.

generación joven

(1) El factor que afecta el buen funcionamiento del programa es el tamaño de la nueva generación. Cuanto mayor sea la generación joven, menos colecciones menores; pero cuando se fija el tamaño del montón, cuanto mayor sea la generación joven, menor la generación anterior y más colecciones importantes.
(2) 8NewRatio refleja la relación de tamaño entre la nueva generación y la generación anterior. NewSize y MaxNewSize reflejan el límite inferior y el límite superior del tamaño de la generación joven. Establecer estos dos valores para que sean iguales fijará el tamaño de la generación joven (igual que Xms y Xmx).
(3) SurvivorRatio también puede optimizar el tamaño del sobreviviente, pero esto tiene poco impacto en el rendimiento. SurvivorRatio es la relación de tamaño entre Eden y Survior.

En términos generales, la aplicación del lado del servidor tendrá las siguientes reglas:

(1) Primero determine el tamaño de almacenamiento dinámico máximo que se puede asignar a la máquina virtual y luego establezca el tamaño óptimo de la generación joven; (
2) Si el tamaño del almacenamiento dinámico es fijo, aumentar el tamaño de la generación joven significa reducir el tamaño de la anterior generación. Haga que la generación anterior sea lo suficientemente grande como para contener todos los objetos sobrevivientes en cualquier momento (deje 10% -20% libre).

selección de tamaño de generación joven

(1) Aplicación de prioridad de tiempo de respuesta: configúrelo lo más grande posible hasta que esté cerca del límite de tiempo de respuesta mínimo del sistema. En este caso, la frecuencia de recopilación de generación joven también es la más pequeña y, al mismo tiempo, reducir el número de objetos que llegan a la generación anterior.
(2) Aplicaciones con prioridad de rendimiento: configúrelo lo más grande posible, posiblemente alcanzando el nivel de Gbit, porque no hay requisitos de tiempo de respuesta y la recolección de basura se puede realizar en paralelo, lo que generalmente es adecuado para aplicaciones con más de 8 CPU.
(3) Evite un ajuste demasiado pequeño. Cuando la configuración de la nueva generación es demasiado pequeña, dará lugar a: ①YGC veces más frecuente; ②Puede causar que los objetos YGC ingresen directamente a la generación anterior.Si la generación anterior está llena en este momento, se activará FGC.

Selección de tamaño de generación anterior

(1) Aplicaciones con prioridad en el tiempo de respuesta: la generación anterior utiliza colectores concurrentes. Si la configuración del montón es pequeña, puede provocar la fragmentación de la memoria, una alta frecuencia de reciclaje y la suspensión de la aplicación, por lo que se usa el método tradicional de marcar y barrer; si el montón es grande, llevará mucho tiempo recopilarlo. En general, debe consultar los siguientes datos:
         información de recolección de basura simultánea, el número de colecciones simultáneas en la generación permanente, información de GC tradicional y la proporción de tiempo dedicado a la recolección de generación joven y generación anterior.
(2) Aplicaciones con prioridad de rendimiento: en general, las aplicaciones con prioridad de rendimiento tienen una gran generación joven y una pequeña generación anterior, de modo que la mayoría de los objetos a corto plazo se pueden reciclar tanto como sea posible y los objetos a mediano plazo se pueden reducir. La vieja generación solo almacena objetos de larga duración.

Problemas de fragmentación causados ​​por montones más pequeños

Debido a que el recopilador concurrente de la generación anterior de CMS utiliza un algoritmo de marcado y barrido , no compacta el almacenamiento dinámico . Cuando el coleccionista reclame, fusionará los espacios adyacentes para que puedan asignarse a objetos más grandes. Sin embargo, cuando el espacio de almacenamiento dinámico es pequeño, aparecerá "fragmentación" después de ejecutarse durante un período de tiempo. Si el recopilador simultáneo no puede encontrar suficiente espacio, el recopilador simultáneo se detendrá. Es posible que se requiera la siguiente configuración:

-XX:+UseCMSCompactAtFullCollection: al usar el recopilador concurrente, active la compresión de la generación anterior.
-XX:CMSFullGCsBeforeCompaction=0: cuando la configuración anterior está habilitada, cuántas veces de Full GC se establece aquí para comprimir la generación anterior.

otras instrucciones

(1) Con un sistema operativo de 64 bits, el jdk de 64 bits en Linux es más lento que el jdk de 32 bits, pero consume más memoria y mayor rendimiento

(2) Las configuraciones XMX y XMS tienen el mismo tamaño, y las configuraciones MaxPermSize y MinPermSize tienen el mismo tamaño, lo que puede reducir la presión ejercida por el tamaño del almacenamiento dinámico escalado.

(3) El objetivo de CMS es el tiempo de pausa de GC más corto. La ventaja de usar CMS es usar la menor cantidad posible de generaciones jóvenes, y luego la generación anterior usa CMS para recopilar en paralelo, lo que puede garantizar la eficiencia de rendimiento del sistema. con baja latencia

(4) Cuando el sistema se detiene, puede ser un problema de GC o un problema de programa. Use jmap y jstack para verificar, o killall -3 java, y luego verifique el registro de la consola java, puede ver muchos problemas

(5) Si se usa el caché, la generación anterior debe ser más grande y el HashMap almacenado en caché no debe tener una longitud ilimitada. Se recomienda usar el algoritmo LRU para el caché. La longitud máxima del LRUMap también debe establecerse de acuerdo con a la situación real.

(6) Cuando se usa el reciclaje simultáneo, la generación joven es más pequeña y la generación anterior es más grande, porque la generación anterior usa el reciclaje simultáneo, incluso si lleva mucho tiempo, no afectará a otros programas para continuar ejecutándose, y el sitio web no te detengas

(7) La configuración de los parámetros de JVM (especialmente la configuración de parámetros como –Xmx –Xms –Xmn -XX:SurvivorRatio -XX:MaxTenuringThreshold) no tiene una fórmula fija y debe medirse de acuerdo con los datos reales del Área antigua de PV, número de YGC, etc. Para evitar fallas en la promoción, la configuración de xmn puede ser demasiado pequeña, lo que también significa que la cantidad de YGC aumentará y la capacidad de manejar el acceso simultáneo disminuirá. El ajuste de cada parámetro requiere pruebas de rendimiento detalladas para encontrar la mejor configuración para una aplicación en particular.

promoción fallida: (promoción fallida)

La promoción falló durante la recolección de basura. En general, puede haber dos razones. La primera razón es que el espacio Para sobrevivir no es suficiente, y los objetos en el espacio no deben moverse a la generación anterior, pero hay muchos objetos en los jóvenes. generación que necesitan ser colocados. Salvar espacio; la segunda razón es que la generación anterior no tiene suficiente espacio para aceptar objetos de la generación joven; en ambos casos, cambiará a Full GC, y el sitio web se detendrá por un largo tiempo.

solución:

  • La solución a la primera razón es eliminar el espacio de rescate, solo configure -XX: SurvivorRatio=65536 -XX: MaxTenuringThreshold=0, pero debido a que el espacio de rescate no se usa, la generación anterior es fácil de llenar y el GC completo la ejecución será más frecuente, por lo que se puede aumentar el espacio de rescate, para que no falle ninguna promoción.
  • Mi solución a la segunda razón es establecer CMSInitiatingOccupancyFraction en un valor determinado (suponiendo 70), de modo que el CMS comience a ejecutarse cuando el espacio de la generación anterior alcance el 70 % y la generación anterior tenga suficiente espacio para aceptar objetos de la generación joven. .

Optimización del rendimiento en la programación real

Los siguientes son algunos puntos a los que se debe prestar atención en el proceso de escribir programas: desarrollar estos hábitos puede reducir el consumo innecesario de memoria hasta cierto punto y reducir aún más el GC continuo causado por memoria insuficiente.

(1) Reducir nuevos objetos. Después de cada nuevo objeto, se debe abrir un nuevo espacio de memoria. Una vez que ya no se hace referencia a estos objetos, deben reciclarse. Por lo tanto, si el objeto se reutiliza razonablemente al máximo, o si se usa el tipo de datos básico en lugar del objeto, ayudará a ahorrar memoria; (2)
Use más variables locales y reduzca el uso de variables estáticas. Las variables locales se crean en la pila para un acceso rápido. Las variables estáticas están en la memoria del montón;
(3) Evite usar finalizar, lo que agregará una gran carga al GC;
(4) Si es de un solo subproceso, intente usar un subproceso no seguro porque la seguridad del subproceso proviene de la sincronización mecanismo, Los mecanismos de sincronización pueden reducir el rendimiento. Por ejemplo, si un programa de subproceso único puede usar HashMap, no use HashTable. De la misma manera, minimice el uso de símbolos sincronizados
(5) Reemplace los símbolos de multiplicación y división con símbolos de desplazamiento. por ejemplo: a*8 debe escribirse como a<<3
(6) Use caché para objetos de uso frecuente;
(7) Intente usar tipos básicos en lugar de tipos empaquetados e intente usar arreglos unidimensionales en lugar de arreglos bidimensionales ;
(8) Intente usar el modificador final, final significa que no se puede modificar y la eficiencia de acceso es alta; (
9) En el caso de un solo hilo (o para variables locales), intente usar StringBuilder para cadenas, que es más rápido que StringBuffer;
(10) ¿Por qué String es lento? Debido a que String es un objeto inmutable, cada vez que se cambia el tipo String, en realidad es equivalente a generar un nuevo objeto String y luego apuntar el puntero al nuevo objeto String. Si no se puede garantizar la seguridad de subprocesos, intente utilizar StringBuffer para concatenar cadenas. Cabe señalar aquí que la capacidad de caché predeterminada de StringBuffer es de 16 caracteres. Si supera los 16, el método append llama al método privado expandCapacity() para garantizar una capacidad de caché suficiente. Por lo tanto, si la capacidad de StringBuffer se puede preestablecer, evite agregar para expandir la capacidad. Si puede garantizar la seguridad de subprocesos, use StringBuilder.

Supongo que te gusta

Origin blog.csdn.net/vcit102/article/details/131800172
Recomendado
Clasificación