objetos matriz index elementos array agregar javascript performance

index - matriz javascript



¿Por qué es arr=[] más rápido que arr=new Array? (4)

Ejecuté este código y obtuve el siguiente resultado. Tengo curiosidad por saber por qué [] es más rápido?

console.time(''using[]'') for(var i=0; i<200000; i++){var arr = []}; console.timeEnd(''using[]'') console.time(''using new'') for(var i=0; i<200000; i++){var arr = new Array}; console.timeEnd(''using new'')

  • usando [] : 299ms
  • usando new : 363ms

Gracias a Raynos aquí hay un benchmark de benchmark de este código y una forma más posible de definir una variable.


Buena pregunta. El primer ejemplo se llama una matriz literal. Es la forma preferida de crear matrices entre muchos desarrolladores. Podría ser que la diferencia de rendimiento se deba a la comprobación de los argumentos de la nueva llamada Array () y luego a la creación del objeto, mientras que el literal crea una matriz directamente.

La diferencia relativamente pequeña en el rendimiento apoya este punto, creo. Por cierto, podría hacer la misma prueba con el Objeto y el objeto literal {}.


Esto tendría algún sentido

Los literales de objetos nos permiten escribir código que admite muchas características y, a la vez, hacerlo relativamente sencillo para los implementadores de nuestro código. No es necesario invocar directamente a los constructores ni mantener el orden correcto de los argumentos pasados ​​a las funciones, etc.

http://www.dyn-web.com/tutorials/obj_lit.php


Expandiendo aún más las respuestas anteriores ...

Desde una perspectiva general de compiladores y sin tener en cuenta las optimizaciones específicas de VM:

Primero, pasamos por la fase de análisis léxico donde tokenizamos el código.

A modo de ejemplo, pueden producirse los siguientes tokens:

[]: ARRAY_INIT [1]: ARRAY_INIT (NUMBER) [1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER) new Array: NEW, IDENTIFIER new Array(): NEW, IDENTIFIER, CALL new Array(5): NEW, IDENTIFIER, CALL (NUMBER) new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER) new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)

Es de esperar que esto le proporcione una visualización suficiente para que pueda comprender cuánto más (o menos) procesamiento se requiere.

  1. Según los tokens anteriores, sabemos como un hecho que ARRAY_INIT siempre producirá una matriz. Por lo tanto, simplemente creamos una matriz y la llenamos. En cuanto a la ambigüedad, la etapa de análisis léxico ya ha distinguido ARRAY_INIT de un objeto de acceso a objetos (por ejemplo, obj[foo] ) o corchetes dentro de cadenas / expresiones regulares (por ejemplo, "foo [] bar" o / [] /)

  2. Esto es minúsculo, pero también tenemos más tokens con el new Array . Además, aún no está del todo claro que simplemente queremos crear una matriz. Vemos la "nueva" señal, pero ¿"nuevo" qué? Luego vemos el token del IDENTIFICADOR, lo que significa que queremos un nuevo "Matriz", pero las VM de JavaScript generalmente no distinguen un token y token de IDENTIFICADOR para "objetos globales nativos". Por lo tanto...

  3. Tenemos que buscar la cadena de alcance cada vez que encontramos un token de IDENTIFICADOR. Las máquinas virtuales Javascript contienen un "objeto de activación" para cada contexto de ejecución que puede contener el objeto "argumentos", variables definidas localmente, etc. Si no podemos encontrarlo en el objeto Activación, comenzamos a buscar la cadena de alcance hasta que alcancemos el alcance global . Si no se encuentra nada, lanzamos un ReferenceError .

  4. Una vez que hemos localizado la declaración de variable, invocamos el constructor. new Array es una llamada de función implícita, y la regla general es que las llamadas a funciones son más lentas durante la ejecución (por lo tanto, los compiladores estáticos de C / C ++ permiten "alineación de funciones", lo que los motores JS JIT como SpiderMonkey deben hacer sobre la marcha )

  5. El constructor Array está sobrecargado. El constructor Array se implementa como código nativo, por lo que proporciona algunas mejoras de rendimiento, pero aún necesita verificar la longitud de los argumentos y actuar en consecuencia. Además, en el caso de que se suministre solo un argumento, necesitamos verificar adicionalmente el tipo del argumento. La nueva matriz ("foo") produce ["foo"] donde la nueva matriz (1) produce [indefinido]

Entonces, para simplificarlo todo: con los literales de matriz, la VM sabe que queremos una matriz; con el new Array , la máquina virtual necesita usar ciclos de CPU adicionales para descubrir qué new Array realmente hace.


Una posible razón es que la new Array requiere una búsqueda de nombre en la Array (puede tener una variable con ese nombre en el alcance), mientras que [] no.