Rendimiento de asignar valores a la matriz

La optimización de código se dice aquí en SO que la creación de perfiles es el primer paso para optimizar javascript y los motores sugeridos son perfiladores de Chrome y Firefox. El problema con ellos es que dicen de alguna manera extraña el momento en que se ejecuta cada función, pero no tengo una buena comprensión de ellos. La forma más útil sería que el generador de perfiles dijera, cuántas veces se ejecuta cada fila y, si es posible, también el tiempo que se pasa en cada fila. De esta manera sería posible ver estrictamente los cuellos de botella. Pero antes de implementar o encontrar dicha herramienta, tenemos dos opciones:

1) haga una calculadora propia que cuente tanto el tiempo como cuántas veces se ejecuta cierto bloque de código o fila 2) aprenda a comprender cuáles son métodos lentos y cuáles no

Para la opción 2jsperf.com Es de gran ayuda. He intentado aprender a optimizar matrices e hice una prueba de velocidad enJSPERF.COM. La siguiente imagen muestra los resultados en 5 navegadores principales y encontró algunos cuellos de botella que no conocía anteriormente.

Los principales hallazgos fueron:

1) La asignación de valores a matrices es significativamente más lenta que la asignación a variables normales a pesar de qué método se utiliza para la asignación.

2) La matriz de preinicialización y / o llenado previo antes de los bucles críticos de rendimiento puede mejorar la velocidad significativamente

3) Las funciones trigonométricas matemáticas no son tan lentas cuando se comparan con empujar valores en matrices (!)

Aquí están las explicaciones de cada prueba:

1. non_array (100%):

Las variables recibieron un valor predefinido de esta manera:

var non_array_0=0;
var non_array_1=0;
var non_array_2=0;
...

y en la región cronometrada se llamaban así:

non_array_0=0;
non_array_1=1;
non_array_2=2;
non_array_3=3;
non_array_4=4;
non_array_5=5;
non_array_6=6;
non_array_7=7;
non_array_8=8;
non_array_9=9;

Lo anterior es una variable similar a una matriz, pero parece que no hay manera de iterar o referirse a esas variables de otra manera como oppocite a matriz. O hay ahi

Nada en esta prueba es más rápido que asignar un número a una variable.

2. non_array_non_pre (83.78%)

Exactamente lo mismo que la prueba 1, pero las variables no fueron preinicializadas ni precargadas. La velocidad es del 83,78% de la velocidad de la prueba 1. En cada navegador probado, la velocidad de las variables precargadas fue más rápida que la no prellenada.Así que inicialice (y posiblemente rellene previamente) las variables fuera de cualquier bucle crítico de velocidad.

El código de prueba está aquí:

var non_array_non_pre_0=0;
var non_array_non_pre_1=0;
var non_array_non_pre_2=0;
var non_array_non_pre_3=0;
var non_array_non_pre_4=0;
var non_array_non_pre_5=0;
var non_array_non_pre_6=0;
var non_array_non_pre_7=0;
var non_array_non_pre_8=0;
var non_array_non_pre_9=0;

3. Pre_filled_array (19.96%):

¡Las matrices son malvadas! Cuando descartamos las variables normales (test1 y test2) y tomamos matrices en la imagen, la velocidad disminuye significativamente.Aunque realizamos todas las optimizaciones (preinicializar y pre-rellenar matrices) y luego asignamos valores directamente sin realizar bucles ni empujar, la velocidad disminuye a 19.96 por ciento. Esto es muy triste y realmente no entiendo por qué ocurre esto. Este fue uno de los choques principales para mí en esta prueba. Las matrices son muy importantes, y no he encontrado una manera de hacer muchas cosas sin matrices.

Los datos de la prueba están aquí:

pre_filled_array[0]=0;
pre_filled_array[1]=1;
pre_filled_array[2]=2;
pre_filled_array[3]=3;
pre_filled_array[4]=4;
pre_filled_array[5]=5;
pre_filled_array[6]=6;
pre_filled_array[7]=7;
pre_filled_array[8]=8;
pre_filled_array[9]=9;

4. non_pre_filled_array (8.34%):

Esta es la misma prueba que 3, pero los miembros de la matriz no están preinicializados ni precargados, solo la optimización fue inicializar la matriz de antemano:var non_pre_filled_array=[];

La velocidad disminuye un 58,23% en comparación con la prueba preinitilizada 3.Por lo tanto, la matriz de preinicialización y / o llenado previo duplica la velocidad.

El código de prueba está aquí:

non_pre_filled_array[0]=0;
non_pre_filled_array[1]=1;
non_pre_filled_array[2]=2;
non_pre_filled_array[3]=3;
non_pre_filled_array[4]=4;
non_pre_filled_array[5]=5;
non_pre_filled_array[6]=6;
non_pre_filled_array[7]=7;
non_pre_filled_array[8]=8;
non_pre_filled_array[9]=9;

5. Pre_filled_array [i] (7.10%):

Luego a los bucles. El método de bucle más rápido en esta prueba. La matriz fue preinicializada y precargada.

La caída de velocidad en comparación con la versión en línea (prueba 3) es 64,44%. Esta es una diferencia tan notable que diría, no haga bucles si no es necesario. Si el tamaño de la matriz es pequeño (no sé qué tan pequeño, se debe probar por separado), es más sabio usar asignaciones en línea en lugar de hacer bucles.

Y como la caída de velocidad es tan grande y realmente necesitamos bucles, es aconsejable encontrarmejor método de bucle (p.ej.while(i--)).

El código de prueba está aquí:

for(var i=0;i<10;i++)
{
  pre_filled_array[i]=i;
}

6. non_pre_filled_array [i] (5.26%):

Si no preinicializamos y rellenamos previamente la matriz, la velocidad disminuye un 25,96%. De nuevo, es aconsejable preinicializar y / o pre-llenado antes de los bucles críticos de velocidad.

El código está aquí:

for(var i=0;i<10;i++) 
{
  non_pre_filled_array[i]=i;
}

7. Cálculos matemáticos (1.17%):

Cada prueba tiene que ser algún punto de referencia. Las funciones matemáticas se consideran lentas. La prueba consistió en diez cálculos matemáticos "pesados", pero ahora viene la otra cosa que me llamó la atención en esta prueba. Mire la velocidad de 8 y 9 donde empujamos diez números enteros para formar una matriz en bucle. Calcular estas 10 funciones matemáticas es más de un 30% más rápido que empujar diez enteros en una matriz en bucle. Por lo tanto, puede ser que sea más fácil convertir algunos empujes de matrices a matrices preinicializadas y mantener esos trigonometría. Por supuesto, si hay cientos o miles de cálculos por cuadro, es aconsejable usar, por ejemplo, sqrt en lugar de sin / cos / tan y use distancias de taxis para las comparaciones de distancias yángulos de diamante (t-radianes) para comparaciones de ángulos, pero aún así, el cuello de botella principal puede estar en otra parte: el bucle es más lento que en el interior, el empuje es más lento que usar la asignación directa con preinitilización y / o precarga, la lógica del código, los algoritmos de dibujo y el acceso a DOM pueden ser lentos. No se puede optimizar todo en Javascript (¡tenemos que ver algo en la pantalla!), Pero todo lo fácil y significativo que podemos hacer es sabio. Alguien aquí en SO ha dicho que el código es para humanos y que el código legible es más esencial que el código rápido, porque el costo de mantenimiento es el mayor. Este es un punto de vista económico, pero he descubierto que la optimización del código puede obtener ambas: elegancia, legibilidad y rendimiento. Y si se logra un aumento de rendimiento del 5% y el código es más directo, ¡da una buena sensación!

El código está aquí:

non_array_0=Math.sqrt(10435.4557);
non_array_1=Math.atan2(12345,24869);
non_array_2=Math.sin(35.345262356547);
non_array_3=Math.cos(232.43575432);
non_array_4=Math.tan(325);
non_array_5=Math.asin(3459.35498534536);
non_array_6=Math.acos(3452.35);
non_array_7=Math.atan(34.346);
non_array_8=Math.pow(234,222);
non_array_9=9374.34524/342734.255;

8. pre_filled_array.push (i) (0.8%):

Empujar es el mal! Empujar combinado a bucle es malvado mal! Esto es, por alguna razón, un método muy lento para asignar valores a una matriz. La prueba 5 (asignaciones directas en bucle), es casi 9 veces más rápida que este método y ambos métodos hacen exactamente lo mismo: asigna el entero 0-9 a la matriz preinicializada y precargada. No he probado si esta maldad de empuje para bucle se debe a empujar o hacer un bucle o la combinación de ambos o el conteo de bucles. Hay en JSPERF.COM otros ejemplos que dan resultados conflictivos. Es mejor probar solo con los datos reales y tomar decisiones. Es posible que esta prueba no sea compatible con otros datos que no sean los utilizados.

Y aquí está el código:

for(var i=0;i<10;i++)
{
  pre_filled_array.push(i);
}

9. non_pre_filled_array.push (i) (0.74%):

El último y más lento método en esta prueba es el mismo que la prueba 8, pero la matriz no está precargada. Un poco más lento que 9, pero la diferencia no es significativa (7.23%). Pero tomemos un ejemplo y comparemos este método más lento con el más rápido.La velocidad de este método es 0.74% de la velocidad del método 1, lo que significa que el método 1 es 135 veces más rápido que esto. Así que piense con cuidado, si las matrices son necesarias en un caso de uso particular. Si es solo uno o pocos empujes, la diferencia de velocidad total no es notable, pero por otro lado, si hay solo unos pocos empujes, son muy simples y elegantes para convertirlos a variables sin arreglos.

Este es el código:

for(var i=0;i<10;i++)
{
  non_pre_filled_array.push(i);
}

Y finalmente la pregunta obligatoria de los SO:

Debido a que la diferencia de velocidad de acuerdo con esta prueba parece ser tan grande entre las asignaciones de variables no de matriz y las asignaciones de matriz, ¿existe algún método para obtener la velocidad de las asignaciones de variable de matriz no y la dinámica de las matrices?

No puedo usarvar variable_$i = 1 en un bucle para que $ i se convierta en algún número entero. Tengo que usarvar variable[i] = 1 que es significativamente más lento quevar variable1 = 1 como probó la prueba. Esto puede ser crítico solo cuando hay matrices grandes y en muchos casos lo son.

EDITAR: Hice una nueva prueba para confirmar la lentitud del acceso a los arreglos y traté de encontrar la manera más rápida:

http://jsperf.com/read-write-array-vs-variable

La lectura de matrices y / o la escritura de matrices son significativamente más lentas que usar variables normales. Si se realizan algunas operaciones para los miembros de la matriz, es más inteligente almacenar el valor del miembro de la matriz en una variable temporal, realizar esas operaciones en la variable temporal y finalmente almacenar el valor en el miembro de la matriz. Y aunque el código se hace más grande, es mucho más rápido hacer esas operaciones en línea que en bucle.

Conclusión: las matrices frente a las variables normales son análogas a la memoria de disco vs. Generalmente, el acceso a la memoria es más rápido que el acceso al disco y el acceso a las variables normales es más rápido que el acceso a la matriz. Y es posible que las operaciones de concatenación también sean más rápidas que usar variables intermedias, pero esto hace que el código sea un poco no legible.

Respuestas a la pregunta(1)

Su respuesta a la pregunta