Dizendo adeus ao asm.js
(spidermonkey.dev)- A partir do Firefox 148, a otimização de asm.js do SpiderMonkey foi desativada por padrão, e o código relacionado será removido em versões futuras
- Como asm.js é um subconjunto de JavaScript, os sites existentes continuarão funcionando, mas serão executados pelo caminho normal de JIT, perdendo os benefícios de otimização
- Recompilar conteúdo asm.js para WebAssembly pode trazer execução mais rápida e binários menores
- O asm.js permitiu execução próxima da nativa dentro de conteúdo web, sem sandbox separado nem APIs alternativas, em resposta a NaCl·PNaCl
- O OdinMonkey, incluído no Firefox 22 em 2013, viabilizou a distribuição na web de projetos C/C++ como Unity e Unreal e serviu de base para o WebAssembly
Desativação da otimização de asm.js
- A partir do Firefox 148, a otimização de asm.js do SpiderMonkey foi desativada por padrão, e todo o código relacionado deverá ser removido em versões futuras
- Os sites que usam asm.js continuarão funcionando
- Como asm.js é um subconjunto do JavaScript comum, o código existente será executado pelo caminho normal de JIT, como qualquer outro script
- No entanto, os benefícios das otimizações específicas de asm.js desaparecem
- Se você ainda distribui conteúdo em asm.js, a recomendação é recompilar para WebAssembly
- Recompilar para WebAssembly pode trazer execução mais rápida e binários menores
- O pipeline de WebAssembly do SpiderMonkey está muito mais avançado do que o pipeline de asm.js
- Com o sucesso do WebAssembly e a migração da maior parte do uso de asm.js, o custo de manter os dois caminhos aumentou
- Continua exigindo tempo de manutenção
- E mantém uma superfície de ataque adicional dentro da VM
O papel do asm.js e o fim do OdinMonkey
- O asm.js foi a resposta da Mozilla à pergunta levantada por NaCl e PNaCl: “é possível executar código em velocidade nativa na web?”
- A ideia era escolher um subconjunto estrito e estaticamente tipado de JavaScript que o mecanismo pudesse reconhecer instantaneamente e compilar para código nativo
- Isso permitia permanecer dentro do conteúdo web e usar as APIs web existentes, sem sandbox separado, IPC ou APIs alternativas
- O asm.js foi incluído no Firefox 22 em 2013 e permitiu que projetos como Unity e Unreal publicassem bases de código C/C++ na web usando apenas tecnologias web padrão
- A demo Epic Citadel foi portada para a web em apenas 4 dias
- O asm.js provou que era possível executar código com desempenho quase nativo usando apenas tecnologias web, abrindo depois o caminho para o WebAssembly
- O WebAssembly foi incluído alguns anos depois no Firefox 52, e é bem possível que ele não existisse sem o asm.js
- O compilador de asm.js se chamava OdinMonkey, e o trabalho de remoção está sendo acompanhado no bug Ragnarök como “Twilight of OdinMonkey”
- O BaldrMonkey, nascido do OdinMonkey, é o compilador otimizador de WebAssembly
- O RabaldrMonkey é o compilador baseline de WebAssembly
- O OdinMonkey entra em processo de aposentadoria após cumprir seu papel por 13 anos
1 comentários
Comentários do Hacker News
asm.js foi a resposta da Mozilla à pergunta levantada por NaCl e PNaCl: “como executar código em velocidade nativa na web?”
Se fosse hoje, o Chrome provavelmente teria simplesmente empurrado NaCl e PNaCl goela abaixo, e então todo mundo estaria reclamando de por que Safari e Firefox não conseguiam acompanhar o padrão da “web”
Por um tempo, eu realmente achei que faríamos tudo no navegador. Em certo sentido, estamos indo cada vez mais nessa direção, mas a experiência geral parece pior do que nunca. Gosto de WASM e quero gostar mais ainda, mas o ritmo de maturação do ecossistema é inacreditavelmente ruim
Pior ainda é que temos ferramentas de IA não confiáveis, e a saída delas precisa ser executada justamente nesse tipo de sandbox, enquanto as empresas estão vendendo exatamente o oposto: sandbox hospedado e VM hospedada baseada em JS
No fim das contas, parece que o problema sempre foi o mesmo. Nunca houve dinheiro em sandbox do lado do cliente
Internamente, foi útil para colocar o Flash player em sandbox, mas as limitações da abordagem baseada em LLVM logo ficaram claras para todos os envolvidos
Se bem me lembro, um grande motivo do fracasso foi que NaCl era uma tecnologia “grande” demais e asm.js uma tecnologia “pequena” demais, então asm.js chegou ao estado pronto para produção antes, apesar de ter começado alguns anos depois
Dito isso, a Apple parece ter aumentado o investimento no WebKit nesta década, depois que as questões regulatórias ficaram sérias, então talvez hoje o resultado fosse diferente
Por isso havia menos reclamações na época, e hoje há reclamações sobre coisas que o Safari não faz porque seriam ruins para a App Store. Felizmente, a UE agora está tentando colocar a Apple um pouco nos trilhos
É triste, mas faz sentido. Um fato interessante é que o Figma começou originalmente com uma base de código totalmente em C++, e asm.js foi essencial para provar que uma ferramenta de design podia rodar no navegador
A migração para WebAssembly só veio depois que eles já tinham clientes pagantes, e a melhora no tempo de carregamento também foi bem grande. asm.js ainda é JS, então o bundle fica maior e o código precisa ser analisado como AST, enquanto no WASM isso não acontece
É parecido com ficar triste porque removeram suporte a i386-unknown-freebsd1
Então agora chegou a morte do asm.js? Estamos nos afastando da linha do tempo da profecia
https://www.destroyallsoftware.com/talks/the-birth-and-death...
Recomendo fortemente se você ainda não viu. Dependendo de como se define “melhor”, pode ser a melhor apresentação técnica de todos os tempos
Um dia, depois de atravessarmos o tempo de guerra e perdermos esse apego psicológico a paradigmas antigos de programação, talvez possamos migrar para algo mais avançado. Claro que isso não significa que o seu banco vai deixar de rodar YavaScript pelos próximos 85 anos, no mínimo
Nunca vou esquecer o momento em que vi a palestra do Gary Bernhardt sobre JavaScript.[0] Foi ali que conheci asm.js pela primeira vez e entrei na toca do coelho de compilar código para rodar no navegador
Agora, 12 anos depois, impressiona quanto da ficção dele virou realidade
[0] https://www.destroyallsoftware.com/talks/the-birth-and-death...
Quando vi aquela palestra pela primeira vez, eu era estagiário, e a empresa fazia internamente o compilador, a IDE e o depurador para umas caixinhas industriais de IO. O compilador era escrito em C, convertido para JS com Emscripten e depois “compilado” junto com a IDE e o depurador em um arquivo HTML gigante, na prática só concatenando tudo. Upload de código e depuração eram feitos por Ethernet, e tudo era empurrado via Ajax
Parece uma arquitetura amaldiçoada, mas os clientes adoravam. Como não era um EXE, não era barrado pelos filtros corporativos exagerados da TI das empresas deles. Por isso nunca migramos para Electron. Em certo sentido, já tinha elementos primitivos de um thick app
Há muito tempo eu escrevi um pequeno capítulo sobre asm.js em um livro de WebGL
https://webglinsights.github.io/
Foi divertido ver a ascensão do asm.js, que era o precursor do WebAssembly. Havia demos iniciais realmente incríveis, como Unreal Engine rodando no navegador. É agridoce vê-lo se pôr aqui, mas ele levou a coisas muito melhores
Talvez precisemos de um transpilador de asm.js para WASM
Compilar código legado com versões legadas do Emscripten é bastante frustrante. Às vezes é quase tão doloroso quanto atualizar o código JS para acompanhar as mudanças acumuladas de ABI do Emscripten
Pelo menos o código asm.js vai continuar funcionando mesmo que a otimização de asm.js seja desligada, mas seria bom ter um conversor
asm.js morreu! Vida longa ao WebAssembly!
Pessoalmente, acho que essa decisão é um erro. Só não sei qual será o impacto real. Pelo que sei, ainda não há tanta gente usando asm.js
Mas o wasm é isolado demais do JavaScript. Depois de usar um pouco de forma limitada, cheguei a pensar em talvez compilar para asm.js em vez disso
Nem tinha certeza se o Emscripten ainda dava suporte completo
No wasm, você não consegue chamar a maioria das APIs web
E, no que eu queria fazer, mais importante ainda, não dá para passar buffers zero-copy do JS para o wasm
Tudo é compromisso. O isolamento é uma vantagem, mas também é uma desvantagem
Já no wasm atual existem tipos GC, e dá até para manter valores JS com externref
Provavelmente também não dá para fazer buffer zero-copy em asm.js. Há uma proposta para buffer zero-copy do lado do wasm: https://github.com/WebAssembly/memory-control/blob/main/prop...
Mesmo no asm.js estrito, você não consegue chamar a maioria das APIs web diretamente. Só há suporte a números; não a strings ou objetos JS, e o heap em C é gerenciado dentro de um objeto ArrayBuffer, como no WASM
O problema do buffer zero-copy é o mesmo. Você precisa sair do asm.js para chamar JavaScript “de verdade”, e também não dá para mapear outro ArrayBuffer diretamente no heap do asm.js, então é preciso copiar. A “FFI de JavaScript” não é tão diferente assim entre asm.js e WASM
Lembro de quando a Mozilla lançou o OdinMonkey, extremamente especializado em código asm.js. Já a equipe do Chrome/V8 preferiu focar em otimizações JIT genéricas que aceleravam JavaScript em geral e também ajudavam asm.js
A diferença de desempenho deixava o Firefox de 2 a 4 vezes na frente, e eles divulgaram isso com bastante força :D
Hoje em dia, a maioria das VMs de JavaScript dos navegadores convergiu para projetos e otimizações muito parecidos, então mesmo sem Odin o código asm.js provavelmente ainda rodaria bem rápido
Meu plano de gerar código JS em tempo de execução para acelerar algoritmos foi por água abaixo. Parece bem mais difícil fazer isso com wasm
Há uma pequena biblioteca que lida com boa parte disso para testes: https://searchfox.org/firefox-main/source/js/src/jit-test/li...
Em JS, provavelmente usaria https://www.npmjs.com/package/binaryen
https://www.assemblyscript.org/
Só não vai ser analisado nem executado tão rápido quanto com um pipeline dedicado a asm.js. A menos que seja um aplicativo enorme, acho que você dificilmente notará tanta diferença