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
En Java hay una instrucción de código de bytes por separado para la asignación de matrices multidimensionales - multianewarray
.
newArray
usos de referenciamultianewarray
de código de bytes;newArray2
invoca sencillanewarray
en el bucle.
El problema es que HotSpot JVM no tiene ninguna vía rápida * de multianewarray
có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.
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 multianewarray
no 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.