¿Por qué WebAssembly es mas rápido que asm.js?

30 septiembre, 2017 22:10 por

Esta es una traducción del artículo original publicado en el blog de Mozilla Hacks.

WebAssembly, es nuevo formato de ejecución para la Web, disponible en la versión estable de la mayoría de navegadores. Uno de los principales objetivos de WebAssembly es ser rápido. Esta entrada explicará detalles técnicos de cómo lo hace.

Por supuesto, “rápido” es relativo. Comparado con JavaScript y otros lenguajes dinámicos, WebAssembly es rápido porque es estáticamente tipado y simple para optimizar. Pero WebAssembly pretende ser tan rápido como el código nativo. asm.js ha estado muy cerca de ello, y WebAssembly cierra la brecha aún más. Esta entrada se enfoca en como WebAssembly es más rápido que asm.js.

Antes de empezar, hay algunas advertencias: el rendimiento es difícil de medir y tiene muchos aspectos. También, en la tecnología siempre van a existir casos donde aún no se han optimizado. Así que no todas las pruebas de rendimiento actuales serán rápidas para WebAssembly. Esta entrada describe cómo WebAssembly debería ser rápido; donde aún no es, es debido a bugs que se deben corregir.

Ahora veamos por qué WebAssembly es rápido:

1. Inicio

WebAssembly está diseñado para ser rápido de descargar y rápido de analizar gramaticalmente, así que incluso las aplicaciones de gran tamaño pueden iniciar rápidamente.

En realidad no es tan fácil mejorar el tamaño de descarga de un archivo de JavaScript minificado y comprimido con gzip, ya que es casi tan compacto como el código nativo. Aún así, el formato binario de WebAssembly puede seguir mejorando, siendo diseñado con cuidado para ser de poco tamaño (los índices son LEB128s, etc.). Suele ser aproximadamente 10–20% mas pequeño (comparado con archivos comprimidos con gzip).

WebAssembly mejora el análisis gramatical en una forma mas grande: puede ser interpretado en un orden de magnitud mas rápido que JavaScript. Esto se debe principalmente a que los formatos binarios son mas rápidos de interpretar, especialmente aquellos diseñados para ello. WebAssembly también facilita analizar (y optimizar) funciones en paralelo, lo cual ayuda mucho en máquinas con múltiples núcleos.

El tiempo total de arranque puede incluir factores mas allá de la descarga y análisis gramatical, tales como la optimización del código de la VM, o descarga de dependencias adicionales antes de la ejecución inicial, entre otros. Pero la descarga y análisis son inevitables y por ello es importante mejorar tanto como se pueda. El resto puede ser optimizado y mitigado, bien sea en el navegador o en la aplicación (por ejemplo, la optimización total del código puede ser evitada usando un compilador base o intérprete para WebAssembly, al inicio).

2. Características de CPU

Un truco que hizo asm.js tan rápido es que, a pesar de que todos los números en JavaScript son doubles, en asm.js tienen una operación and de bits al final, lo que hace que sea lógicamente igual a un CPU haciendo una suma de enteros, algo en lo que los CPU son muy buenos. Así que asm.js facilitó a las VM usar el poder de los CPUs al máximo.

Pero asm.js estaba limitado a cosas que son expresadas en JavaScript. WebAssembly no está limitado a ello y nos deja usar características adicionales de la CPU tales como:

  • Enteros de 64 bits. Las operaciones en ellos pueden ser hasta 4 veces mas rápidas. Esto permite acelerar algoritmos de cifrado, por ejemplo.
  • Traslado de carga y almacenamiento. Es una gran ayuda, básicamente en todo lo que use memoria de objetos con campos fijos (structs de C, entre otros).
  • Cargas y almacenamiento no alineado, evita la necesidad de asm.js de enmascarar (que asm.js lo hace para compatibilidad con los vectores tipados). Esto ayuda prácticamente con cualquier carga y almacenamiento.
  • Varias instrucciones de CPU como popcount, copysign, etc. Cada uno de éstos ayudan en circunstancias específicas (ejem. popcount puede ayudar en el cryptonalisis).

Qué tanto beneficiará una prueba de rendimiento específica dependerá del uso de las características mencionadas anteriormente. Generalmente vemos una mejora de velocidad del 5% en promedio respecto a asm.js. Las futuras mejoras mejoras esperadas son el soporte de instrucciones SIMD.

3. Mejoras en el ecosistema de herramientas

WebAssembly principalmente es un objetivo de compilación, y por lo tanto tiene 2 partes: compiladores que lo generan (el lado del conjunto de las herramientas), y las máquinas virtuales (VM) que lo ejecutan (el lado del navegador). Un buen rendimiento depende de ambos.

Este ya era el caso con asm.js, y Emscripten hizo muchas optimizaciones en el lado de las herramientas, corriendo optimizadores de LLVM y también el optimizador de asm.js de Emscripten. Para WebAssembly, se ha construido encima de ello, pero hemos añadido mejoras significantes mientras se hacía. Tanto asm.js como WebAssembly no son objetivos de compilación comunes, y en maneras similares, se aprendieron lecciones durante los días asm.js que ayudaron a hacer mejor las cosas para WebAssembly. Particularmente:

En general, estas mejoras ayudan tanto que migrar de asm.js a WebAssembly ayudo a mejorar un (7% y 5% en Box2D, respectivamente).

4. Buen rendimiento

asm.js podía correr básicamente a velocidad nativa, pero nunca pudo hacer de forma consistente en todos los navegadores. La razón es que unos los optimizaron para una manera y otros de otra forma, produciendo diferentes resultados. Con el tiempo las cosas empezaron a converger, pero el problema era que asm.js no era un estándar: era una especificación formal de un subconjunto de JavaScript, escrito por un solo proveedor, que vio gradualmente interés por otros creadores de navegadores.

WebAssembly, por otra parte, ha sido diseñado en conjunto por todos los principales navegadores. A diferencia de JavaScript, que se puede hacer rápido usando muchos métodos creativos, o asm.js, que podía hacerse rápido usando métodos sencillos pero no todos los navegadores lo hicieron. WebAssembly tiene más acuerdos de como se debe optimizar. Aún existe mucho campo para para la diferenciación de VMs (diferentes formas de realizar la compilación, AOT vs. JIT, entre otros.), pero una buena base de rendimiento predecible se puede esperar para toda la Web.

The following two tabs change content below.
Colaborador de Mozilla Venezuela e Hispano en las áreas de desarrollo y medios sociales, entre otros. También soy desarrollador Web, Skateboarder, Profesor universitario, jugador de Playstation y PC, usuario Linux, Blogger, Geek, entre otros.

Compartir artículo:

Start the discussion at foro.mozilla-hispano.org

cc-by-sa