Análisis de escape / asignación en la pila / reemplazo escalar / eliminación de sincronización

Análisis de escape

Prefacio

sabemos:

  • Algunos tipos básicos de datos variables (int / short / long / byte / float / double / boolean / char) y referencias a objetos se almacenan en la pila.
  • Los objetos se almacenan principalmente en el montón, es decir, los objetos creados por la nueva palabra clave.

Sin embargo, hay una descripción de la memoria del montón de Java en "Comprensión profunda de la máquina virtual de Java":

  • Con el desarrollo de la que avanza la tecnología de análisis del compilador JIT que escapan, 栈上分配, 标量替换优化技术dará lugar a algunos cambios sutiles, todos los objetos se asignan en el montón se ha convertido en cada vez menos "absolutamente" la.

Durante la compilación, JIT realizará muchas optimizaciones en el código. Parte del propósito de la optimización es 减少内存堆分配压力que se llama una de las tecnologías importantes 逃逸分析.

逃逸分析(Escape Analysis)Es la tecnología de optimización más avanzada de la máquina virtual Java actual. Esta es una forma eficaz de reducir el programa Java 同步负载y 内存堆分配压力el 跨函数全局数据流algoritmo de análisis. A través del análisis de escape, el compilador de Java Hotspot puede analizarlo 一个新对象的引用的使用范围从而决定是否要将这个对象分配到堆上.

El comportamiento básico del análisis de escape es el análisis 对象动态作用域: cuando un objeto se define en un método, puede ser referenciado por un método externo, por ejemplo, como un parámetro de llamada pasado a otros lugares, llamado 方法逃逸.

Por ejemplo lo siguiente 方法返回值逃逸:

public static StringBuffer craeteStringBuffer(String s1, String s2) {
    
    
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb;
}

StringBuffer sbEs una variable interna de un método. El código anterior sbregresará directamente . Luego, esto StringBufferpuede ser cambiado por otros métodos, de modo que su alcance no esté solo dentro del método. Aunque es una variable local, se dice que escapa al fuera del método. Incluso se puede acceder a él mediante subprocesos externos, como la asignación a variables de clase o variables de instancia a las que se puede acceder en otros subprocesos, llamados 线程逃逸.

Si desea que el código anterior StringBuffer sbno escape del método, puede escribirlo así:

public static String createStringBuffer(String s1, String s2) {
    
    
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb.toString();
}

No regrese directamente StringBuffer, entonces StringBufferel método no se escapará.

El análisis de escape incluye:

  • Escape de asignación de variable global
  • Escape del valor de retorno del método
  • Escape de referencia de instancia
  • Escape de subproceso: asignación a variables de clase o variables de instancia a las que se puede acceder en otros subprocesos

como sigue:

public class EscapeAnalysis {
    
    
 
     public static Object object;
     
     public void globalVariableEscape(){
    
       //全局变量赋值逃逸  
         object =new Object();  
      }  
     
     public Object methodEscape(){
    
        //方法返回值逃逸
         return new Object();
     }
     
     public void instancePassEscape(){
    
       //实例引用发生逃逸
        this.speak(this);
     }
     
     public void speak(EscapeAnalysis escapeAnalysis){
    
    
         System.out.println("Escape Hello");
     }
}

Mediante el análisis de escape, el compilador puede optimizar el código de la siguiente manera:

  1. Se omite la sincronización . Si se encuentra que un objeto es accesible solo desde un hilo, entonces la operación de este objeto puede ignorarse.
  2. Convierta la asignación de pila en asignación de pila . Si se asigna un objeto en una subrutina, de modo que el puntero al objeto nunca se escape, el objeto puede ser un candidato para la asignación de pila en lugar de la asignación de montón.
  3. Objetos separados o reemplazos escalares . Es posible que algunos objetos no necesiten existir como una estructura de memoria continua para acceder, por lo que es posible que parte (o todo) del objeto no se almacene en la memoria, sino que se almacene en el registro de la CPU.

Cuando se está ejecutando código Java, puede especificar si habilitar el análisis de escape a través de los parámetros de JVM:

  • -XX:+DoEscapeAnalysis : Indica que se abre el análisis de escape

  • -XX:-DoEscapeAnalysis : Indica cerrar el análisis de escape

Desde JDK 1.7, el análisis de escape se ha habilitado de forma predeterminada. Si necesita deshabilitarlo, debe especificar-XX:-DoEscapeAnalysis

A continuación, presentaré principalmente el segundo propósito del análisis de escape: convertir la asignación de pila en asignación de pila

Asignación en la pila

A través de la asignación de memoria de JVM, podemos saber que los objetos en JAVA están asignados en el montón. Cuando el objeto no está referenciado, necesitamos confiar en el GC para recuperar la memoria. Si el número de objetos es grande, traerá más presión sobre el GC, también afecta indirectamente el rendimiento de la aplicación.

为了减少临时对象在堆内分配的数量,JVM通过逃逸分析确定如果该对象不会被外部访问Luego, 标量替换asigne memoria en la pila para el objeto, de modo que el espacio de memoria ocupado por el objeto pueda destruirse cuando el marco de la pila se extraiga de la pila, lo que reduce la presión de la recolección de basura.

Sustitución escalar

Escalar (escalar) y agregado (agregado)

标量Es decir, la cantidad que no se puede descomponer más, y el tipo de datos básico de JAVA es un escalar (como los tipos de datos básicos como int, long y tipos de referencia, etc.).

El opuesto de un escalar es una cantidad que se puede descomponer aún más, y esta cantidad se llama 聚合量. En JAVA, un objeto es una cantidad agregada que se puede descomponer aún más.

Proceso de reemplazo escalar

Al 逃逸分析determinar que no se accederá al objeto de forma externa y que el objeto se puede descomponer aún más, la JVM no creará el objeto, sino que lo 成员变量descompondrá en varias variables miembro utilizadas por este método. Estas variables miembro sustituidas asignan espacio en 栈帧o 寄存器.

Si desensambla un objeto Java y restaura sus variables miembro a variables dispersas, esto se llama 标量替换. Las variables desensambladas se pueden analizar y optimizar por separado, y el espacio se puede asignar en el registro de actividad (marco de pila o registro) por separado, y el objeto original no necesita asignar espacio como un todo.

Eliminación de sincronización

La eliminación de la sincronización es una tecnología de optimización proporcionada por la máquina virtual Java. Mediante el análisis de escape, puede determinar si otros subprocesos accederán a un objeto.

Si hay un método en una clase 同步锁, pero solo un subproceso accede a él en 机器码tiempo de ejecución, el bloqueo de sincronización se eliminará después del análisis de escape en este momento , que es 线程逃逸la situación que no ocurrió . Entonces no habrá competencia de recursos en la lectura y escritura del objeto, y se puede eliminar el bloqueo de sincronización en el objeto.

Al -XX:+EliminateLockspermitir la eliminación de sincronización, prueba la eficiencia de ejecución

public static void main(String[] args) {
    
    
    long start = System.currentTimeMillis();
    EscapeAnalysis escapeAnalysis = new EscapeAnalysis();
    for (int i = 0; i < 1000000; i++) {
    
    
      	escapeAnalysis.createString("Escape", "Hello");
    }
    long bufferCost = System.currentTimeMillis() - start;
    System.out.println("craeteString: " + bufferCost + " ms");
}

public String createString(String ... values){
    
    
    StringBuffer stringBuffer = new StringBuffer(); 
    for (String str : values) {
    
    
      	stringBuffer.append(str + " ");
    }
    return stringBuffer.toString();
}   
-server -XX:+DoEscapeAnalysis -XX:-EliminateLocks
craeteString: 202 ms
 
-server -XX:+DoEscapeAnalysis -XX:+EliminateLocks
craeteString: 173 ms

Se puede ver en los resultados de la prueba que si se habilita la cancelación de sincronización, la eficiencia de ejecución de habilitar la cancelación de sincronización es mayor que la de no habilitar la cancelación de sincronización.

Supongo que te gusta

Origin blog.csdn.net/weixin_44471490/article/details/111502696
Recomendado
Clasificación