Los límites de WebAssembly y la importancia del tree-shaking
-
WebAssembly, a pesar de mucho interés y expectativas, solo ha tenido un éxito limitado en la web
- Hay casos exitosos como Photoshop, pero en general no hay muchos proyectos que aprovechen WebAssembly
- En especial, WebAssembly no es adecuado para apps que usan mucho el DOM
- Una de las principales razones es la diferencia entre los modelos de programación de JavaScript y WebAssembly
-
WebAssembly no ha tenido mucho éxito fuera de lenguajes como C o Rust
- Lenguajes como C# tienen la incomodidad de tener que incluir también un runtime como el recolector de basura
- Sin embargo, se espera que la situación mejore porque pronto se incorporarán nuevas funciones de WebAssembly que soportan tipos por referencia y recolección de basura
La capacidad de optimización de código del compilador es la clave del éxito de WebAssembly
-
Para que WebAssembly tenga éxito en la web, los compiladores deben poder generar código pequeño y eficiente
- Es importante mantener tamaños de archivo pequeños, del orden de unos pocos kilobytes
- Si no, no queda otra que depender del hype o de una base de usuarios específica
-
En el mundo de JavaScript, la optimización del tamaño del código se logra mediante bundlers y herramientas similares
- Tree-shaking es una técnica que incluye solo las funciones y tipos de datos que realmente se usan en el programa
-
Tree-shaking es un término ampliamente usado, aunque sea una metáfora inadecuada tanto en sentido horticultural como algorítmico
Estado actual del tree-shaking en otros lenguajes
-
En lenguajes con runtimes pesados como Go o Python, el tree-shaking todavía no está bien optimizado
- Incluso el programa más simple en Go supera los 2 MB al compilarse a WebAssembly
- Pyodide de Python también requiere descargar archivos de alrededor de 20 MB
-
En entornos de servidor, el tamaño del binario no suele ser un gran problema
- Para entornos limitados como móviles, también se desarrollan toolchains más ligeras por separado, como MicroPython y TinyGo
-
Las implementaciones de lenguajes para la web inevitablemente tienen que diferir de las existentes
- Porque interactuar con el DOM es en sí mismo un entorno particular
- En el caso de ClojureScript, las diferencias con Clojure se documentan por separado
Discusión sobre el algoritmo de tree-shaking
-
El compilador Hoot Scheme que está desarrollando el autor actualmente genera código Wasm de alrededor de 70 KB
- Incluir solo definiciones de funciones (procedimientos) es relativamente fácil
- Pero hay varios puntos difíciles como los siguientes
-
En el modelo de evaluación de
letrec*, los bindings son recursivos y además tienen orden, lo que dificulta el análisis del compilador- En el caso de los tipos de registro, los callbacks de la vtable hacen que mucho código permanezca vivo
-
Si se usan funciones con alto grado de polimorfismo como
display, se incluye mucho código relacionado- Es mejor usar funciones concretas como
write-string
- Es mejor usar funciones concretas como
-
Para un tree-shaking óptimo se necesita flow analysis
- Si se sabe que no se pasa un argumento bitvector a
display, se puede eliminar el código relacionado
- Si se sabe que no se pasa un argumento bitvector a
-
En Python es todavía más difícil debido al despacho dinámico y a funciones dinámicas como
__getattr__- La estructura de módulos de Python también complica el tree-shaking
Resumen
- Gracias al soporte de GC, en WebAssembly será posible programar el DOM con lenguajes distintos de JavaScript
- Pero para reducir lo suficiente el tamaño del resultado, se requiere una inversión considerable en el toolchain de cada lenguaje
- Se necesitan un toolchain independiente que aplique algoritmos de tree-shaking y optimización de la biblioteca estándar
Opinión de GN⁺
-
Con el soporte de GC en WebAssembly, se podrán usar varios lenguajes en el desarrollo web, pero parece que hay muchas dificultades para llevarse sin más los toolchains existentes. Da la impresión de que harán falta implementaciones de lenguajes y técnicas de optimización especializadas para la web.
-
Para que el tree-shaking funcione bien en lenguajes de tipado dinámico, parece indispensable el análisis estático. Pero en lenguajes como Python, que tienen muchas funciones dinámicas, no parece nada fácil. Quizá incluso podría ser una opción crear desde el principio un lenguaje más favorable al análisis estático.
-
Proyectos experimentales como Hoot o TinyGo parecen buenas referencias. Pero todavía podría ser demasiado pronto para aplicar este tipo de proyectos en productos reales. Probablemente no quede otra que mejorar de forma gradual.
-
Si se trata de un proyecto donde el rendimiento no es tan sensible y lo importante es desarrollar rápido, algo como Pyodide podría valer la pena. Pero si el producto prioriza la experiencia de usuario, por ahora JavaScript parece la mejor opción.
-
También podría pensarse en incorporar funciones como tree-shaking dentro del propio WebAssembly. Pero no sería fácil porque los requisitos varían según el lenguaje. Además, si aparece un lenguaje que soporte muy bien el tree-shaking, tal vez convenga más programar directamente en ese lenguaje. Da curiosidad ver cómo se repartirá el rol entre WebAssembly y los lenguajes de programación.
1 comentarios
Opinión de Hacker News
En resumen, es lo siguiente:
floatVecen lugar deHashMaptalc)randyfxhash)mainy solo el código alcanzable se incluye en el binario final.