[Volver a publicar] El espacio de caché de código JVM es insuficiente, lo que resulta en un rendimiento de servicio lento

Espacio de caché de código JVM insuficiente, lo que resulta en un rendimiento de servicio lento

https: // www.jianshu.com/p/4214df5df334

 

Según los comentarios comerciales, después de que una aplicación en línea se haya ejecutado durante un período de tiempo, después del período pico, de repente descubrí que la capacidad de procesamiento ha disminuido y el tiempo de respuesta de la interfaz se ha vuelto más largo, pero mirando los datos del GC en Cat, todo es normal.

Verifique los registros a través de la máquina en el trampolín y encuentre un registro que rara vez se ve:

Java HotSpot(TM) 64-Bit Server VM warning: CodeCache is full. Compiler has been disabled. Java HotSpot(TM) 64-Bit Server VM warning: Try increasing the code cache size using -XX:ReservedCodeCacheSize=. ... “CompilerThread0” java.lang.OutOfMemoryError: requested 2854248 bytes for Chunk::new. Out of swap space? 

CodeCache está lleno, lo que indica que Code Cache está lleno, lo que hace que el compilador falle. ¿Por qué es esto?

Primero, tenemos que entender qué es Code Cache.

¿Qué es la caché de código?

El código Java activará la compilación JIT cuando el número de ejecuciones alcance un umbral. Una vez que el bloque de código se compila en el código de máquina local, el código de máquina local compilado se ejecutará directamente la próxima vez que se ejecute. Por lo tanto, el código de máquina local debe almacenarse en caché, y el área de memoria del código de máquina local almacenada en caché es Code Cache, que no forma parte del montón de Java. Además del código compilado JIT, el código de método nativo (JNI) utilizado por Java También existe en codeCache.

Ajuste de caché de código

Dado que Code Cache es un área de memoria, debe haber un límite de tamaño, pero para diferentes versiones de JVM y diferentes métodos de inicio, el tamaño predeterminado de Code Cache también es diferente, lo que se jinfo -flag ReservedCodeCacheSize puede verificar.

Después de que el servicio comience, a medida que pase el tiempo, definitivamente habrá más y más métodos compilados por JIT en el código de máquina local y almacenados en Code Cache. Dado que el tamaño de Code Cache es fijo, existe el riesgo de que se agote.

Una vez que se llena el caché de código, ocurrirá lo siguiente:

  • La función JIT de la JVM se detendrá y no se compilará ningún código adicional.
  • El código compilado aún se ejecuta de manera compilada, pero el código que no se ha compilado solo puede ejecutarse de manera interpretada.

En este caso, si todavía hay mucho código en la aplicación ejecutada de manera interpretada, su rendimiento se verá muy reducido. Para evitar esta situación, necesita una comprensión más profunda de Code Cache.

Cuando se inicia la JVM, la memoria requerida por Code Cache se inicializará por separado. En este momento, el montón de Java también se inicializará, por lo que Code Cache y el montón de Java son dos áreas de memoria separadas.

En codeCache.cppel CodeCache::initialize()método, se realiza la inicialización de Code Cache

 

Code Cache contiene 3 tipos de datos:

  • NonNMethodCode
  • Código Profilizado
  • Código sin perfil

A través de los SegmentedCodeCacheparámetros, puede elegir si desea inicializar de acuerdo con el conjunto o el segmento.

-XX:ReservedCodeCacheSizeEl tamaño de inicialización de Code Cache se puede especificar a través de parámetros. Este valor predeterminado es diferente en diferentes versiones de JDK. Actualmente, estoy depurando OpenJDK11 aquí. El tamaño predeterminado es 240M, que es suficiente.

Puede ver el tamaño predeterminado de otras versiones:

 

Para aquellos con solo 32M y 48M, puede haber un peligro oculto de Caché de Código insuficiente, y el aumento ReservedCodeCacheSizepuede ser una solución, pero esto generalmente es solo una solución temporal.

Afortunadamente, la JVM proporciona un método de recuperación codeCache más radical: enjuague especulativo.

Este método de recuperación está habilitado de forma predeterminada después de JDK1.7.0_4, y la versión anterior debe habilitarse con un parámetro: -XX: + UseCodeCacheFlushing.

Con el vaciado especulativo habilitado, cuando la caché de código es insuficiente:

  • La primera mitad de los métodos compilados se colocará en una lista antigua para reciclar;
  • Dentro de cierto intervalo de tiempo, si no se llama al método en la lista anterior, este método se borrará de la caché de código;

Desafortunadamente, en JDK1.7, el enjuague especulativo liberó algo de espacio, pero desde el registro de compilación, JIT no volvió a la normalidad, y el rendimiento general del sistema cayó mucho y se produjo un gran número de tiempos de espera.

Vi un error de este tipo en el sitio web oficial de Oracle: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8006952  Debido a problemas con el algoritmo, cuando la caché de código es insuficiente, el hilo de compilación no puede continuar y consume mucha CPU. Hace que el sistema funcione más lento.

 

 

 
 
A 37 personas les gusta esto
 

Supongo que te gusta

Origin www.cnblogs.com/jinanxiaolaohu/p/12612672.html
Recomendado
Clasificación