Despidiéndonos de asm.js
(spidermonkey.dev)- Desde Firefox 148, la optimización de asm.js en SpiderMonkey quedó desactivada por defecto y el código relacionado se eliminará en futuras versiones
- asm.js es un subconjunto de JavaScript, así que los sitios existentes seguirán funcionando, pero se ejecutarán por la ruta normal de JIT y perderán sus ventajas de optimización
- Si se vuelve a compilar contenido asm.js a WebAssembly, se puede obtener una ejecución más rápida y binarios más pequeños
- asm.js permitió una ejecución casi nativa dentro del contenido web, sin sandbox separado ni APIs alternativas, como respuesta frente a NaCl·PNaCl
- OdinMonkey, incorporado en Firefox 22 en 2013, hizo posible distribuir en la web proyectos C/C++ como Unity y Unreal, y sentó las bases para WebAssembly
Desactivación de la optimización de asm.js
- Desde Firefox 148, la optimización de asm.js en SpiderMonkey quedó desactivada por defecto, y en futuras versiones se eliminará todo el código relacionado
- Los sitios que usan asm.js seguirán funcionando
- asm.js es un subconjunto de JavaScript común, por lo que el código existente se ejecutará por la ruta normal de JIT como cualquier otro script
- Sin embargo, se pierden las ventajas de optimización específicas de asm.js
- Si todavía distribuyes contenido en asm.js, se recomienda volver a compilarlo a WebAssembly
- Al recompilar a WebAssembly, se puede obtener una ejecución más rápida y binarios más pequeños
- La tubería de WebAssembly en SpiderMonkey está mucho más desarrollada que la de asm.js
- Como WebAssembly tuvo éxito y la mayor parte del uso de asm.js ya migró, el costo de mantener ambas rutas al mismo tiempo se volvió alto
- Sigue requiriendo tiempo de mantenimiento
- Queda una superficie de ataque adicional dentro de la VM
El papel de asm.js y el cierre de OdinMonkey
- asm.js fue la respuesta de Mozilla a la pregunta que planteaban NaCl y PNaCl: “¿se puede ejecutar código a velocidad nativa en la web?”
- El enfoque consistía en tomar un subconjunto estricto y estáticamente tipado de JavaScript, que el motor pudiera reconocer al vuelo, y compilarlo a código nativo
- Podía mantenerse dentro del contenido web y usar las APIs web existentes, sin sandbox separado, IPC ni APIs alternativas
- asm.js se incorporó en Firefox 22 en 2013, y permitió que proyectos como Unity y Unreal publicaran sus bases de código C/C++ en la web usando solo tecnologías web estándar
- La demo de Epic Citadel fue portada a la web en apenas 4 días
- asm.js demostró que era posible ejecutar código con velocidad casi nativa usando solo tecnologías web, y abrió el camino hacia WebAssembly
- WebAssembly se incorporó algunos años después en Firefox 52, y es muy probable que WebAssembly no existiera sin asm.js
- El compilador de asm.js se llamaba OdinMonkey, y su eliminación se sigue en el bug Ragnarök bajo el nombre “Twilight of OdinMonkey”
- BaldrMonkey, nacido de OdinMonkey, es el compilador optimizador de WebAssembly
- RabaldrMonkey es el compilador baseline de WebAssembly
- OdinMonkey entra en su etapa final tras 13 años de servicio
1 comentarios
Comentarios en Hacker News
asm.js fue la respuesta de Mozilla a la pregunta que plantearon NaCl y PNaCl: “¿cómo ejecutar código a velocidad nativa en la web?”
Si hubiera sido ahora, Chrome simplemente habría impuesto NaCl y PNaCl, y entonces todos habrían estado quejándose de por qué Safari y Firefox no podían seguir los estándares de la “web”
Durante un tiempo pensé seriamente que terminaríamos haciendo todo en el navegador. En cierto sentido, cada vez pasa más, pero la experiencia general se siente peor que nunca. Me gusta WASM y quiero que me guste, pero la velocidad de maduración del ecosistema es increíblemente pobre
Peor aún, necesitamos ejecutar herramientas de IA no confiables y sus resultados justo dentro de ese tipo de sandbox, pero las empresas están vendiendo exactamente lo contrario: sandboxes alojados y VMs alojadas basadas en JS
Al final, parece que siempre fue el mismo problema. No había dinero en el sandbox del lado del cliente
Internamente fue útil para aislar el reproductor de Flash, pero las limitaciones del enfoque basado en LLVM pronto se hicieron evidentes para todos los involucrados
Si no recuerdo mal, una razón importante de que fracasara fue que NaCl era una tecnología demasiado “grande” y asm.js una demasiado “pequeña”, así que asm.js llegó a estar listo para producción primero, aunque había empezado varios años después
Pero Apple sí parece haber aumentado su inversión en WebKit en esta década, después de que la presión regulatoria se volviera seria, así que hoy el resultado podría ser distinto
Por eso en aquel momento hubo menos quejas, y ahora sí las hay por cosas que Safari no hace porque perjudicarían a la App Store. Por suerte, la UE ahora está intentando corregir un poco a Apple
Es triste, pero tiene sentido. Como dato curioso, Figma empezó originalmente como una base de código completamente en C++, y asm.js fue clave para demostrar que una herramienta de diseño podía ejecutarse en el navegador
El cambio a WebAssembly ocurrió después de conseguir clientes de pago, y la mejora en tiempo de carga también fue bastante grande. asm.js seguía siendo JS, así que el bundle era más grande y había que parsear el código como AST, mientras que WASM no tiene ese problema
Es como ponerse triste porque ya no exista soporte para i386-unknown-freebsd1
¿Entonces ya llegó la muerte de asm.js? Nos estamos alejando de la línea temporal de la profecía
https://www.destroyallsoftware.com/talks/the-birth-and-death...
Si todavía no la han visto, la recomiendo muchísimo. Dependiendo de cómo se defina “la mejor”, podría ser la mejor charla técnica de todos los tiempos
Algún día, después de pasar por la época de guerra y soltar el apego psicológico a paradigmas de programación obsoletos, podremos avanzar a algo más progresista. Claro, eso no significa que tu banco vaya a dejar de correr YavaScript en al menos los próximos 85 años
Nunca voy a olvidar el momento en que vi la charla de JavaScript de Gary Bernhardt.[0] Ahí fue cuando conocí por primera vez asm.js, y también caí por la madriguera de compilar código para que corriera en el navegador
Ahora, 12 años después, me sorprende cuánto de su ficción terminó volviéndose realidad
[0] https://www.destroyallsoftware.com/talks/the-birth-and-death...
Cuando vi esa charla por primera vez, era practicante, y la empresa hacía su propio compilador, IDE y depurador para unas pequeñas cajas de IO industrial. El compilador estaba escrito en C, lo convertimos a JS con Emscripten y luego lo “compilábamos” junto con el IDE y el depurador en un archivo HTML gigantesco, o sea, en realidad solo lo concatenábamos. La subida de código y la depuración iban por Ethernet, y todo se empujaba con Ajax
Suena como una arquitectura maldita, pero a los clientes les encantaba. Como no era un EXE, no lo bloqueaban los filtros exagerados de TI corporativa de sus empresas. Por eso nunca migramos a Electron. En cierto sentido, sí tenía elementos primitivos de una thick app
Hace mucho escribí un pequeño capítulo sobre asm.js en un libro de WebGL
https://webglinsights.github.io/
Fue divertido ver el ascenso de asm.js, que fue el precursor de WebAssembly. Entre las primeras demos había cosas realmente impresionantes, como Unreal Engine corriendo en el navegador. Da algo de nostalgia ver aquí su ocaso, pero dio paso a cosas mucho mejores
Tal vez haga falta un transpilador de asm.js a WASM
Compilar código legado con versiones legadas de Emscripten es bastante frustrante. A veces es tan doloroso como actualizar el código JS para ajustarlo a los cambios acumulados del ABI de Emscripten
Al menos el código asm.js va a seguir funcionando aunque se desactiven las optimizaciones de asm.js, pero estaría bien tener un convertidor
¡asm.js ha muerto! ¡Larga vida a WebAssembly!
Personalmente creo que esta decisión es un error. Aunque no sé qué tan grande será el impacto real. Que yo sepa, ya no mucha gente usa asm.js
Pero wasm está demasiado aislado de JavaScript. Después de usarlo de forma limitada, llegué a pensar que quizá preferiría compilar a asm.js
Ni siquiera estaba seguro de que Emscripten siguiera dándole soporte completo
En wasm no se puede llamar a la mayoría de las APIs web
Y en lo que yo quería hacer, era todavía más importante que no se pudiera pasar un buffer de cero copias de JS a wasm
Todo tiene compensaciones. El aislamiento es una ventaja, pero también una desventaja
En cambio, hoy wasm ya tiene tipos GC y también puedes retener valores de JS con externref
Probablemente tampoco podrías hacer buffers de cero copias en asm.js. Del lado de wasm hay una propuesta para eso: https://github.com/WebAssembly/memory-control/blob/main/prop...
Incluso en asm.js estricto no puedes llamar directamente a la mayoría de las APIs web. Solo soporta números, no strings ni objetos de JS, y administra el heap de C dentro de un objeto ArrayBuffer, igual que WASM
Los buffers de cero copias tienen el mismo problema. Tienes que salir de asm.js hacia JavaScript “real” para hacer la llamada, y tampoco puedes mapear otro ArrayBuffer directamente dentro del heap de asm.js, así que necesitas copiar. El “JavaScript FFI” en la práctica no es tan distinto entre asm.js y WASM
Recuerdo cuando Mozilla presentó OdinMonkey, extremadamente especializado para código asm.js. En cambio, el equipo de Chrome/V8 se enfocó en optimizaciones JIT más generales que aceleraran JavaScript en general y también ayudaran a asm.js
La diferencia de velocidad favorecía a Firefox por un factor de 2 a 4, y le dieron bastante publicidad :D
Hoy en día, la mayoría de las VMs de JavaScript de los navegadores han convergido hacia diseños y optimizaciones muy parecidos, así que incluso sin Odin el código asm.js probablemente se ejecutaría bastante rápido de todos modos
Mi plan de generar código JS en tiempo de ejecución para acelerar algoritmos se fue al traste. Hacer esto con wasm parece mucho más difícil
Hay una pequeña librería que se encarga de buena parte de ese trabajo para pruebas: https://searchfox.org/firefox-main/source/js/src/jit-test/li...
En JS, probablemente terminarías usando https://www.npmjs.com/package/binaryen
https://www.assemblyscript.org/
Solo que ya no se parseará ni ejecutará tan rápido como con una canalización dedicada a asm.js. A menos que sea una aplicación gigantesca, no creo que vayas a notar mucho la diferencia