Llevo un par de semanas con el nuevo invento de Google instalado en el equipo y todavía no me lo creo. Cuando a principios de mes lanzaron Chrome, pensé: «Vale, otro navegador más para pelearme con los CSS». Ya teníamos suficiente guerra intentando que las webs cuadraran en Firefox, el incombustible Opera y el insufrible Internet Explorer (bendito IE6 que sigue sin querer morir en las empresas). Pero tras probar un par de dashboards cargados de scripts de AJAX, me di cuenta de que aquí pasaba algo distinto. La interfaz no se colgaba. No había ese molesto lag al hacer scroll en páginas pesadas. Chrome va como un misil, y el culpable tiene nombre y apellido: el motor V8.
De la interpretación pura a la compilación JIT
Hasta ahora, la forma en que los navegadores ejecutaban JavaScript era, para entendernos, bastante rudimentaria. Eran intérpretes clásicos: leen el código, lo parsean y lo van ejecutando sobre la marcha. Eso está bien para validar un formulario de registro o hacer un simple menú desplegable, pero a estas alturas le pedimos mucho más a la web. Ahí están GMail o Google Maps demostrando lo que se puede llegar a montar.
Lo que han hecho los ingenieros de Google (o más bien, el equipo danés que ficharon) con V8 es romper la baraja: han metido un compilador Just-In-Time (JIT). En lugar de interpretar el código cada vez, V8 lo compila directamente a código máquina nativo (x86 o ARM) en el momento de la ejecución. Es fascinante pensar que ahora llevamos bajo el capó un motor aplicando técnicas que hasta hace nada veíamos exclusivas en máquinas virtuales de lenguajes pesados como Java.
El truco de las clases ocultas
JavaScript es un lenguaje dinámico; no definimos si una variable es un entero o un puntero, y podemos añadir propiedades a un objeto cuando nos dé la gana. Esto volvía locos a los motores a la hora de buscar cosas en memoria. V8 soluciona esto usando lo que llaman «clases ocultas» (hidden classes).
Si creamos objetos con la misma estructura, V8 genera internamente una clase en C++ y agiliza el acceso a la memoria saltándose la típica búsqueda en el diccionario de propiedades. Fijaos en este fragmento de código que podríamos escribir en cualquier proyecto:
function Usuario(nombre, edad) {
this.nombre = nombre;
this.edad = edad;
}
var admin = new Usuario("Pepe", 35);
var invitado = new Usuario("Juan", 28);
En Firefox o IE, el motor guarda esos objetos como un simple diccionario de claves y valores (un hash map). Cada vez que accedes a admin.edad, tiene que calcular el hash y buscar la clave. V8, por debajo, se da cuenta de que admin e invitado comparten la misma estructura exacta. Crea una clase oculta para ellos y sabe en qué offset de memoria está la edad. El acceso pasa de ser una búsqueda lenta a una instrucción de lectura rapidísima a nivel de procesador.
Y no sólo eso. Tienen un recolector de basura (Garbage Collector) generacional muy agresivo que pausa la ejecución en fracciones de milisegundo, por lo que ya no sufres esos congelamientos repentinos de pantalla cuando al navegador le da por limpiar la memoria RAM (algo de lo que ya hablé sobre nuestra huida de Internet Explorer, pero llevado a otro nivel).
El futuro está en el navegador
La web está mutando rápido. Ya no construimos simples páginas con enlaces, estamos haciendo aplicaciones completas que viven dentro de una pestaña. Y si vamos a programar interfaces ricas en el cliente, necesitamos potencia bruta.
Creo que lo que ha hecho Google con Chrome y V8 no es solo sacar un navegador más bonito o minimalista; es lanzar un órdago a la cara de Mozilla y Microsoft. Nos han demostrado que JavaScript no es un lenguaje lento por naturaleza, sino que los intérpretes que usábamos eran mediocres. Si esta escalada de rendimiento sigue a este ritmo, quién sabe, igual en un par de años estamos corriendo lógicas pesadísimas o cálculos complejos directamente en el navegador, sin depender de plugins cerrados como Flash para ganar agilidad.
De momento, a nivel de desarrollo, Chrome ya se ha ganado un hueco fijo en mi barra de tareas, aunque solo sea para testear hasta qué velocidad pueden llegar a ejecutarse mis scripts.