As limitações do WebAssembly e a importância do tree-shaking
-
Apesar de muito interesse e expectativa, o WebAssembly teve apenas um sucesso limitado na web
- Existem casos de sucesso como o Photoshop, mas no geral não há muitos projetos que usem WebAssembly
- Em especial, o WebAssembly não é adequado para apps que usam muito o DOM
- Uma das principais razões é a diferença entre os modelos de programação de JavaScript e WebAssembly
-
O WebAssembly não teve muito sucesso fora de linguagens como C ou Rust
- Linguagens como C# têm a inconveniência de precisar fornecer junto runtimes como o garbage collector
- Porém, espera-se que a situação melhore em breve, já que novos recursos do WebAssembly com suporte a reference types e garbage collection devem ser introduzidos
A capacidade de otimização de código dos compiladores é a chave para o sucesso do WebAssembly
-
Para o WebAssembly ter sucesso na web, os compiladores precisam conseguir gerar código pequeno e eficiente
- É importante manter arquivos pequenos, na faixa de alguns kilobytes
- Caso contrário, só resta depender de hype ou de uma base de usuários específica
-
No ecossistema JavaScript, a otimização do tamanho do código já é feita por meio de bundlers e afins
- Tree-shaking é a técnica de incluir apenas as funções e os tipos de dados realmente usados no programa
-
Tree-shaking é um termo amplamente usado, embora seja uma metáfora inadequada tanto do ponto de vista horticultural quanto algorítmico
A situação do tree-shaking em outras linguagens
-
Em linguagens com runtimes pesados, como Go ou Python, o tree-shaking ainda não está otimizado
- Mesmo o programa mais simples em Go, quando compilado para WebAssembly, passa de 2 MB
- O Pyodide, de Python, também exige o download de cerca de 20 MB de arquivos
-
Em ambientes de servidor, o tamanho do binário não costuma ser um grande problema
- Para ambientes restritos, como mobile, também são desenvolvidos toolchains mais leves separadamente, como MicroPython e TinyGo
-
Implementações de linguagens voltadas para a web inevitavelmente precisam ser diferentes das existentes
- Isso porque interagir com o DOM é, por si só, um ambiente peculiar
- No caso do ClojureScript, as diferenças em relação ao Clojure são documentadas separadamente
Discussão sobre algoritmos de tree-shaking
-
O compilador Hoot Scheme, em desenvolvimento pelo autor, atualmente gera cerca de 70 KB de código Wasm
- Incluir apenas definições de funções (procedures) é relativamente fácil
- Mas existem alguns pontos difíceis, como os abaixo
-
No modelo de avaliação de
letrec*, os bindings são recursivos e ao mesmo tempo ordenados, o que dificulta a análise pelo compilador- No caso de record types, callbacks de vtable acabam mantendo muito código vivo
-
Ao usar funções altamente polimórficas, como
display, muito código relacionado acaba sendo incluído- É melhor usar funções mais concretas, como
write-string
- É melhor usar funções mais concretas, como
-
Para um tree-shaking ideal, é necessária flow analysis
- Se soubermos que um argumento bitvector não é passado para
display, podemos remover o código relacionado
- Se soubermos que um argumento bitvector não é passado para
-
Em Python, isso é ainda mais difícil por causa de recursos dinâmicos como despacho dinâmico e
__getattr__- A estrutura de módulos do Python também é um fator que complica o tree-shaking
Resumo
- Com suporte a GC, o WebAssembly passa a permitir programação de DOM em linguagens além de JavaScript
- Mas, para tornar o tamanho do resultado suficientemente pequeno, é necessário um investimento considerável no toolchain de cada linguagem
- São necessários o desenvolvimento de toolchains separados com algoritmos de tree-shaking aplicados e a otimização das bibliotecas padrão
A opinião do GN⁺
-
Com o suporte a GC no WebAssembly, tornou-se possível usar várias linguagens no desenvolvimento web, mas parece haver muitas dificuldades em simplesmente levar os toolchains das linguagens existentes como estão. Parece que será preciso desenvolver implementações de linguagem e técnicas de otimização especializadas para o ambiente web.
-
Para que o tree-shaking funcione bem em linguagens de tipagem dinâmica, a análise estática parece ser indispensável. Mas linguagens como Python têm muitos recursos dinâmicos, então isso não deve ser fácil. Talvez uma alternativa seja criar desde o início uma nova linguagem mais favorável à análise estática.
-
Projetos experimentais como Hoot e TinyGo parecem ser boas referências. Mas talvez ainda seja cedo para aplicar esse tipo de projeto em produtos reais. Provavelmente não há outro caminho além de melhorias graduais.
-
Para projetos em que desempenho não é tão sensível e a velocidade de desenvolvimento é mais importante, algo como Pyodide pode valer a pena. Mas, para produtos em que a experiência do usuário é prioridade, no momento JavaScript ainda parece ser a melhor escolha.
-
Também dá para imaginar colocar no próprio WebAssembly algum recurso parecido com tree-shaking. Mas isso não deve ser simples, porque os requisitos variam conforme a linguagem. E, se surgir uma linguagem que dê ótimo suporte a tree-shaking, talvez passe a valer mais a pena programar diretamente nela. Fica a curiosidade sobre como será dividida a responsabilidade entre WebAssembly e linguagens de programação.
1 comentários
Comentários do Hacker News
Em resumo, é o seguinte:
floatVecem vez deHashMaptalc)randefxhash)maine inclui no binário final apenas o código que pode ser alcançado.