¿Los navegadores analizan JavaScript en cada carga de página?

190

¿Los navegadores (IE y Firefox) analizan los archivos de JavaScript vinculados cada vez que se actualiza la página?

Pueden almacenar en caché los archivos, por lo que supongo que no intentarán descargarlos cada vez, pero como cada página está esencialmente separada, espero que eliminen cualquier código antiguo y lo vuelvan a analizar.

Esto es ineficiente, aunque perfectamente comprensible, pero me pregunto si los navegadores modernos son lo suficientemente inteligentes como para evitar el paso de análisis dentro de los sitios. Estoy pensando en casos en los que un sitio usa una biblioteca javascript, como ExtJS o jQuery, etc.

ajreal
fuente
44
Mi 2c: siento que los beneficios de rendimiento del almacenamiento en caché de archivos JavaScript analizados son demasiado pequeños para que esto sea una optimización significativa.
Itay Maman
2
Desde mis puntos de referencia, en realidad podría importar. Por ejemplo, el tiempo de carga de jQuery es de alrededor de 30 ms (en una máquina de escritorio rápida), de los cuales el 20% solo analiza el código en una representación ejecutable, y el resto lo está ejecutando, es decir, inicializando el objeto jQuery en este caso. Si está en un dispositivo móvil y usa dos o tres bibliotecas, este retraso podría ser relevante, ya que la ejecución de JavaScript está bloqueando y la página está esencialmente en blanco hasta que cada script JS se carga en la memoria.
djjeck

Respuestas:

338

Estos son los detalles que he podido desenterrar. Vale la pena señalar primero que, aunque generalmente se considera que JavaScript se interpreta y ejecuta en una VM, este no es realmente el caso con los intérpretes modernos, que tienden a compilar la fuente directamente en el código de la máquina (con la excepción de IE).


Chrome: motor V8

V8 tiene un caché de compilación. Esto almacena JavaScript compilado usando un hash de la fuente para hasta 5 recolecciones de basura. Esto significa que dos partes idénticas de código fuente compartirán una entrada de caché en la memoria, independientemente de cómo se incluyeron. Este caché no se borra cuando se vuelven a cargar las páginas.

Fuente


Actualización - 19/03/2015

El equipo de Chrome ha publicado detalles sobre sus nuevas técnicas para la transmisión y el almacenamiento en caché de JavaScript .

  1. Streaming de guiones

La transmisión de secuencias de comandos optimiza el análisis de archivos JavaScript. [...]

A partir de la versión 41, Chrome analiza los scripts asíncronos y diferidos en un hilo separado tan pronto como la descarga ha comenzado. Esto significa que el análisis puede completar solo milisegundos después de que la descarga haya finalizado, y hace que las páginas se carguen hasta un 10% más rápido.

  1. Almacenamiento en caché de código

Normalmente, el motor V8 compila el JavaScript de la página en cada visita, convirtiéndolo en instrucciones que entiende un procesador. Este código compilado se descarta una vez que un usuario navega fuera de la página, ya que el código compilado depende en gran medida del estado y el contexto de la máquina en el momento de la compilación.

Chrome 42 presenta una técnica avanzada para almacenar una copia local del código compilado, de modo que cuando el usuario regrese a la página, se puedan omitir los pasos de descarga, análisis y compilación. En todas las cargas de página, esto permite que Chrome evite aproximadamente el 40% del tiempo de compilación y ahorre una batería preciosa en dispositivos móviles.


Opera: motor Carakan

En la práctica, esto significa que siempre que un programa de script está a punto de compilarse, cuyo código fuente es idéntico al de otro programa que se compiló recientemente, reutilizamos el resultado anterior del compilador y omitimos el paso de compilación por completo. Esta memoria caché es bastante efectiva en escenarios de navegación típicos en los que se carga página tras página desde el mismo sitio, como artículos de noticias diferentes de un servicio de noticias, ya que cada página a menudo carga la misma biblioteca de scripts, a veces muy grande.

Por lo tanto, JavaScript se almacena en caché en las recargas de la página, dos solicitudes al mismo script no darán lugar a una nueva compilación.

Fuente


Firefox: motor de SpiderMonkey

SpiderMonkey utiliza Nanojitcomo su back-end nativo, un compilador JIT. El proceso de compilación del código de la máquina se puede ver aquí . En resumen, parece recompilar los scripts a medida que se cargan. Sin embargo, si echamos un vistazo más de cerca a las partes internas Nanojit, vemos que el monitor de nivel superior jstracer, que se utiliza para realizar un seguimiento de la compilación, puede realizar la transición a través de tres etapas durante la compilación, proporcionando un beneficio para Nanojit:

El estado inicial del monitor de rastreo es el monitoreo. Esto significa que spidermonkey está interpretando bytecode. Cada vez que spidermonkey interpreta un bytecode de salto hacia atrás, el monitor toma nota de la cantidad de veces que se saltó el valor del contador de programa (PC) del objetivo de salto. Este número se llama el recuento de visitas para la PC. Si el recuento de visitas de una PC en particular alcanza un valor umbral, el objetivo se considera activo.

Cuando el monitor decide que una PC de destino está activa, busca en una tabla hash de fragmentos para ver si hay un fragmento que contenga código nativo para esa PC de destino. Si encuentra dicho fragmento, pasa al modo de ejecución. De lo contrario, pasa al modo de grabación.

Esto significa que para los hotfragmentos de código, el código nativo se almacena en caché. Lo que significa que no será necesario volver a compilar. No está claro si estas secciones nativas hash se retienen entre las actualizaciones de la página. Pero supongo que lo son. Si alguien puede encontrar evidencia de apoyo para esto, entonces excelente.

EDITAR : Se ha señalado que el desarrollador de Mozilla Boris Zbarsky ha declarado que no Gecko compilado caché guiones todavía . Tomado de esta respuesta SO .


Safari: JavaScriptCore / SquirelFish Engine

Creo que la mejor respuesta para esta implementación ya la ha dado otra persona .

Actualmente no almacenamos en caché el código de bytes (o el código nativo). Es una
opción que hemos considerado, sin embargo, actualmente, la generación de código es una
parte trivial del tiempo de ejecución de JS (<2%), por lo que no estamos buscando
esto en este momento.

Esto fue escrito por Maciej Stachowiak , el desarrollador principal de Safari. Así que creo que podemos tomar eso como cierto.

No pude encontrar ninguna otra información, pero puedes leer más sobre las mejoras de velocidad del último SquirrelFish Extrememotor aquí , o navegar por el código fuente aquí si te sientes aventurero.


IE: Chakra Engine

No hay información actual sobre el motor JavaScript de IE9 (Chakra) en este campo. Si alguien sabe algo, por favor comente.

Esto no es oficial, pero para las implementaciones de motores más antiguas de IE, Eric Lippert ( un desarrollador de MS de JScript ) afirma en una respuesta de blog aquí que:

JScript Classic actúa como un lenguaje compilado en el sentido de que antes de que se ejecute cualquier programa JScript Classic, verificamos completamente el código, generamos un árbol de análisis completo y generamos un código de bytes. Luego ejecutamos el bytecode a través de un intérprete de bytecode. En ese sentido, JScript está tan "compilado" como Java. La diferencia es que JScript no le permite persistir ni examinar nuestro código de bytes patentado . Además, el código de bytes tiene un nivel mucho más alto que el código de bytes JVM: el lenguaje de código de bytes JScript Classic es poco más que una linealización del árbol de análisis, mientras que el código de bytes JVM está claramente destinado a operar en una máquina de pila de bajo nivel.

Esto sugiere que el código de bytes no persiste de ninguna manera y, por lo tanto, el código de bytes no se almacena en caché.

Jivings
fuente
10
+1, excelente redacción. Sin embargo, con respecto a Firefox, consulte esta pregunta de StackOverflow donde el desarrollador de Mozilla, Boris Zbarsky, explica que Gecko actualmente no hace esto.
cha0site
Gracias, lo vi en mis viajes pero no pude encontrar ninguna otra evidencia de apoyo. Editaré la respuesta con ella.
Jivings
1
Tenga en cuenta que lo que se dijo sobre IE se dijo en 2003: el primer lanzamiento del motor JS de IE9 fue en IE9 en 2011.
gsnedders
Además, Opera almacena en caché el bytecode JS en más que solo recargas. (Sin embargo, el código de máquina generado no se almacena en caché).
gsnedders
2
@Jivings Tome lo anterior como fuente. (Soy una de las personas en el equipo Carakan.)
gsnedders
12

Opera lo hace, como se menciona en la otra respuesta. ( fuente )

Firefox (motor SpiderMonkey) no almacena en caché el código de bytes. ( fuente )

WebKit (Safari, Konqueror) no almacena en caché el código de bytes. ( fuente )

No estoy seguro acerca de IE [6/7/8] o V8 (Chrome), creo que IE podría hacer algún tipo de almacenamiento en caché mientras que V8 no. IE es de código cerrado, así que no estoy seguro, pero en V8 puede que no tenga sentido almacenar en caché el código "compilado", ya que compilan directamente al código de la máquina.

cha0site
fuente
1
IE6–8 casi seguramente no lo hará. IE9 podría, pero no tengo ninguna evidencia de ninguna manera. El JS compilado probablemente no se almacena en caché en ninguna parte porque a menudo es bastante grande.
gsnedders
@gsnedders: No estoy seguro de que IE8 no pueda hacerlo técnicamente, parece que también se compila para bytecode (no oficial pero cercano), por lo que no hay ninguna razón técnica para no almacenar eso en caché. IE9 parece agregar un JIT para compilar en código nativo.
cha0site
2
Bytecode ha sido usado por IE para ... para siempre. No es nada nuevo en IE8. Es solo que, dado un intérprete, el rendimiento del intérprete es mucho más lento que el tiempo de análisis es completamente irrelevante. IE9 tiene un motor JS completamente nuevo (desde cero), por lo que no se sigue nada entre los dos.
gsnedders
3

Que yo sepa, solo Opera almacena en caché el JavaScript analizado. Consulte la sección "Programas compilados en caché" aquí .

gsnedders
fuente
gracias, ¿tiene más detalles sobre otra familia de navegadores también?
ajreal
2

No vale nada que Google Dart aborde explícitamente este problema a través de "Instantáneas": el objetivo es acelerar la inicialización y el tiempo de carga al cargar la versión preparada del código.

InfoQ tiene una buena crítica @ http://www.infoq.com/articles/google-dart

igrigorik
fuente
0

Creo que la respuesta correcta sería "no siempre". Por lo que entiendo, tanto el navegador como el servidor desempeñan un papel en la determinación de lo que se almacena en caché. Si realmente necesita que los archivos se vuelvan a cargar cada vez, creo que debería poder configurarlos desde Apache (por ejemplo). Por supuesto, supongo que el navegador del usuario podría configurarse para ignorar esa configuración, pero probablemente eso sea poco probable.

Así que me imagino que en la mayoría de los casos prácticos, los archivos javascript en sí se almacenan en caché, pero se reinterpretan dinámicamente cada vez que se carga la página.

Zachary Murray
fuente
0

El navegador definitivamente utiliza el almacenamiento en caché, pero sí, los navegadores analizan el JavaScript cada vez que se actualiza una página. Porque cada vez que el navegador carga una página, crea 2 árboles: 1.Content tree y 2.render tree.

Este árbol de renderizado consiste en la información sobre el diseño visual de los elementos dom. Por lo tanto, cada vez que se carga una página, se analiza el javascript y cualquier cambio dinámico del javascript le gustará posicionar el elemento dom, mostrar / ocultar elemento, agregar / eliminar elemento hará que el navegador vuelva a crear el árbol de renderizado. Pero los broswers modernos como FF y Chrome lo manejan de manera ligeramente diferente, tienen el concepto de renderizado incremental, por lo que siempre que haya cambios dinámicos por js como se mencionó anteriormente, solo hará que esos elementos se rendericen y repinten nuevamente.

Abhidev
fuente