¿Por qué la asignación de un único 2D matriz tardar más de un bucle de asignación de varias matrices 1D del mismo tamaño y la forma total de?

user10339780:

Pensé que sería más rápido para crear directamente, pero de hecho, la adición de bucles toma sólo la mitad del tiempo. ¿Qué pasó que ralentizó tanto?

Aquí está el código de prueba

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class Test_newArray {
    private static int num = 10000;
    private static int length = 10;

    @Benchmark
    public static int[][] newArray() {
        return new int[num][length];
    }

    @Benchmark
    public static int[][] newArray2() {
        int[][] temps = new int[num][];
        for (int i = 0; i < temps.length; i++) {
            temps[i] = new int[length];
        }
        return temps;
    }

}

Los resultados del ensayo son como sigue.

Benchmark                Mode  Cnt    Score   Error  Units
Test_newArray.newArray   avgt   25  289.254 ± 4.982  us/op
Test_newArray.newArray2  avgt   25  114.364 ± 1.446  us/op

El entorno de prueba es el siguiente

JMH versión: 1.21

versión VM: JDK 1.8.0_212, OpenJDK 64 bits del servidor VM, 25.212-b04

apangin:

En Java hay una instrucción de código de bytes por separado para la asignación de matrices multidimensionales - multianewarray.

  • newArrayusos de referencia multianewarrayde código de bytes;
  • newArray2invoca sencilla newarrayen el bucle.

El problema es que HotSpot JVM no tiene ninguna vía rápida * de multianewarraycódigo de bytes. Esta instrucción se ejecuta siempre en la máquina virtual en tiempo de ejecución. Por lo tanto, la asignación no se colocarán en línea en el código compilado.

El primer punto de referencia tiene que pagar penalización en el rendimiento de la conmutación entre los contextos de Java VM y el tiempo de ejecución. También, el código de asignación común en el tiempo de ejecución VM (escrito en C ++) no es tan optimizado como la asignación inline en código JIT-compilado, sólo porque es genérica , es decir, no optimizado para el tipo de objeto particular o para el sitio de llamada particular, se realiza comprobaciones de tiempo de ejecución adicionales, etc.

Estos son los resultados de perfiles de ambos puntos de referencia con asíncrono de perfiles . Solía JDK 11.0.4, pero para JDK 8 la imagen se ve similar.

newArray

newArray2

En el primer caso, 99% de tiempo que se gasta en el interior OptoRuntime::multianewarray2_C- el código de C ++ en el tiempo de ejecución VM.

En el segundo caso, la mayor parte de la gráfica es de color verde, lo que significa que el programa se ejecuta en su mayoría en contexto Java, en realidad la ejecución de código JIT-compilado optimizado específicamente para el punto de referencia dado.

EDITAR

* Solo para aclarar: en HotSpot multianewarrayno está optimizado muy bien por diseño. Es bastante costoso de implementar una operación tan compleja en ambos compiladores JIT correctamente, mientras que los beneficios de esta optimización serían cuestionables: asignación de matrices multidimensionales no suele ser un cuello de botella en una aplicación típica.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=304922&siteId=1
Recomendado
Clasificación