asm.js
Surgido em 21 de março de 2013
Criado por Mozilla
Influenciada por JavaScript
Influenciou WebAssembly
Sistema operacional Multiplataforma
Página oficial asmjs.org

asm.js é um subconjunto de JavaScript projetado para permitir que software de computador escrito em linguagens como C sejam executados como aplicativos da web, enquanto mantém características de desempenho consideravelmente melhores do que o JavaScript padrão, que é a linguagem típica usada para tais aplicativos.

o asm.js consiste em um subconjunto estrito de JavaScript, para o qual o código escrito em linguagens estaticamente tipadas com gerenciamento de memória manual (como C) é traduzido por um compilador de fonte para fonte como o Emscripten (baseado em LLVM). O desempenho é melhorado ao limitar os recursos da linguagem àqueles que podem ser otimizados com antecedência e outras melhorias de desempenho.

O Mozilla Firefox foi o primeiro navegador da web a implementar otimizações específicas para o asm.js, a partir da versão 22.

O asm.js foi substituído por WebAssembly. Consulte § Deprecação abaixo.

Design

O asm.js permite melhorias significativas de desempenho para aplicativos da web, mas não tem como objetivo melhorar o desempenho do código JavaScript escrito à mão, nem permite nada além do desempenho aprimorado.

Destina-se a ter características de desempenho mais próximas das do código nativo do que o JavaScript padrão, limitando os recursos da linguagem àqueles passíveis de otimização antecipada e outras melhorias de desempenho. Ao usar um subconjunto de JavaScript, o asm.js é amplamente compatível com todos os principais navegadores da web, ao contrário de abordagens alternativas como o Google Native Client.

Geração de código

O asm.js normalmente não é escrito diretamente: em vez disso, como uma linguagem intermediária, ele é gerado por meio do uso de um compilador que pega o código-fonte em uma linguagem como C++ e gera asm.js.

Por exemplo, dado o seguinte código em C:

int f(int i) {
  return i + 1;
}

Emscripten produziria o seguinte código em JS:

function f(i) {
  i = i|0;
  return (i + 1)|0;
}

Observe a adição de |0 e a falta de especificadores de tipo. Em JavaScript, os operadores bit a bit convertem seus operandos em inteiros assinados de 32 bits e fornecem resultados inteiros. Isso significa que um OR bit a bit com zero converte um valor em um inteiro (uma apresentação "conceitual" muito simples de operadores bit a bit pode não lidar com a conversão de tipo, mas toda linguagem de programação define operadores para sua própria conveniência, como o Javascript faz aqui) . Ao fazer isso para cada parâmetro, isso garante que, se a função for chamada de um código externo, o valor será convertido para o tipo correto. Isso também é usado no valor de retorno, neste caso, para garantir que o resultado da adição de 1 a i seja um número inteiro (caso contrário, ele poderia se tornar muito grande) e para marcar o tipo de retorno da função. Essas conversões são exigidas pelo asm.js, para que um compilador otimizador possa produzir código nativo ahead-of-time altamente eficiente. Nesse compilador otimizador, nenhuma conversão é executada quando o código asm.js chama outro código asm.js, pois os especificadores de tipo necessários significam que é garantido que os valores já terão o tipo correto. Além disso, em vez de realizar uma adição de ponto flutuante e converter para um número inteiro, ele pode simplesmente fazer uma operação de número inteiro nativo. Juntos, isso leva a benefícios em desempenho significativos.

Aqui está outro exemplo para calcular o comprimento de uma string:

size_t strlen(char *ptr) {
  char *curr = ptr;
  while (*curr != 0) {
    curr++;
  }
  return (curr - ptr);
}

Isso resultaria no seguinte código em asm.js:

function strlen(ptr) {
  ptr = ptr|0;
  var curr = 0;
  curr = ptr;
  while ((MEM8|0) != 0) {
    curr = (curr + 1)|0;
  }
  return (curr - ptr)|0;
}

No código gerado, a variável MEM8 é na verdade uma "visualização" byte a byte de um buffer tipado, que serve como o "heap" do código em asm.js.

Desempenho

Como o asm.js é executado em um navegador, o desempenho depende muito do navegador e do hardware. Os benchmarks preliminares de programas C compilados para asm.js estão geralmente em um fator de lentidão de 2 em relação à compilação nativa com Clang.

Muito desse ganho de desempenho em relação ao JavaScript normal é devido a 100% de consistência de tipo e virtualmente nenhuma coleta de lixo (a memória é gerenciada manualmente em uma grande matriz tipada). Este modelo mais simples, sem comportamento dinâmico, sem alocação ou desalocação de memória, apenas um conjunto estreito de inteiros bem definidos e operações de ponto flutuante permite um desempenho muito maior e potencial de otimização.

O benchmark da Mozilla de dezembro de 2013 mostrou melhorias significativas: "Firefox com otimizações float32 pode rodar todos esses benchmarks em cerca de 1,5× mais lento do que o nativo, ou melhor." A Mozilla aponta que o desempenho do código compilado nativamente não é uma medida única, mas sim um intervalo, com diferentes compiladores nativos (neste caso Clang e GCC) entregando código de desempenho diferente. "Na verdade, em alguns benchmarks, como Box2D, FASTA e cópia, asm.js é tão próximo ou mais próximo do Clang do que o Clang está do GCC. Em um caso, o asm.js até supera o Clang por pouco no Box2D."

Implementações

O projeto Emscripten fornece ferramentas que podem ser usadas para compilar bases de código C e C ++ (ou qualquer outra linguagem que possa ser convertida para LLVM IR) em asm.js.

Todos os navegadores com suporte para ECMAScript 6 devem ser capazes de executar o código asm.js, pois é um subconjunto dessa especificação. No entanto, como os recursos foram adicionados nessa edição para habilitar o suporte completo para asm.js (Math.fround()), navegadores mais antigos sem esses recursos podem encontrar problemas.

Algumas implementações de navegador são especialmente otimizadas para asm.js:

  • Mozilla Firefox foi o primeiro navegador da web a implementar otimizações específicas do asm.js, começando com o Firefox 22. OdinMonkey, o compilador asm.js da Mozilla usado no Firefox, é um componente do IonMonkey, o compilador JIT do SpiderMonkey.
  • A Microsoft está implementando suporte para asm.js em Chakra, o mecanismo JavaScript usado pelo Microsoft Edge, realizando validação para produzir código JIT altamente otimizado.
  • As otimizações do motor JavaScript V8 do Google Chrome no Chrome 28 fizeram benchmarks do asm.js mais de duas vezes mais rápido do que as versões anteriores do Chrome, embora o V8 do Chrome não use compilação antecipada.

Adoção

Quase todos os aplicativos atuais baseados em asm.js são aplicativos C/C++ compilados em asm.js usando Emscripten ou Mandreel. Com isso em mente, o tipo de aplicativo que terá como alvo o asm.js em um futuro próximo são aqueles que se beneficiarão da portabilidade de execução em um navegador, mas que têm um nível de complexidade para o qual um porte direto para JavaScript seria inviável.

Até agora, uma série de linguagens de programação, frameworks de aplicativos, programas, bibliotecas, jogos, motores de jogos e outros softwares já foram portados. Alguns deles são listados abaixo.

Linguagens de programação

Frameworks de aplicativos

  • pepper.js: Portes de diversos apps PNaCl (earth, voronoi, bullet, etc.)
  • Qt: portes de vários demos da Qt, mais os aplicativos do KDE, como o Kate

Programas e bibliotecas

Motores de jogo

Jogos

Emuladores

  • EM-DOSBox: um porte do DOSBox para o Emscripten
  • Start9.io: uma plataforma de emulação da web visando múltiplas arquiteturas de jogos
  • JSMESS: um porte do emulador MESS para muitos consoles de jogos e sistemas de computadores

Matemática

Deprecação

O asm.js se tornou obsoleto principalmente com a introdução do WebAssembly (wasm), que tem um formato de bytecode que é mais rápido de analisar. Os esforços para estender o JavaScript com mais recursos de baixo nível, como SIMD.js, também foram suspensos desde 2017.

o asm.js permanece útil principalmente como um "substituto" para o wasm, por meio de um programa escrito pela organização WebAssembly que converte o wasm em asm.js. Não há um conversor dedicado de asm.js para wasm, mas os compiladores TypeScript-para-wasm podem ser usados parcialmente. O emissor WebAssembly de referência binaryen costumava conter um módulo asm2wasm, mas foi removido depois que o Emscripten parou de usá-lo.

Ver também

Referências

  1. «asm.js in Firefox Nightly». Luke Wagner's blog. 21 de março de 2013. Consultado em 12 de maio de 2021 
  2. a b «kripken/emscripten · GitHub». Github.com. Consultado em 12 de maio de 2021 
  3. a b «Firefox 22.0 release notes». Mozilla. Consultado em 12 de maio de 2021 
  4. «Asm.js». Asm.js. Consultado em 12 de maio de 2021 
  5. «asm.js — frequently asked questions». Asmjs.org. 26 de julho de 2014 
  6. «asm.js». Asm.js. Consultado em 12 de maio de 2021 
  7. a b Alon Zakai; Robert Nyman (20 de dezembro de 2013). «Gap between asm.js and native performance gets even narrower with float32 optimizations». Consultado em 12 de maio de 2021 
  8. «Bringing Asm.js to Chakra and Microsoft Edge». Microsoft. 7 de maio de 2015. Consultado em 12 de maio de 2021 
  9. «Chrome 28 Beta: A more immersive web, everywhere». Google. Consultado em 12 de maio de 2021 
  10. «Home — Demos — Games and Game Engines» 
  11. «Lua REPL». Kripken.github.io. Consultado em 12 de maio de 2021. Arquivado do original em 8 de junho de 2013 
  12. «plu». Themucker.github.io. Consultado em 12 de maio de 2021. Arquivado do original em 3 de agosto de 2013 
  13. «repl.it — Python». Repl.it. Consultado em 12 de maio de 2021 
  14. «repl.it — Ruby». Repl.it. Consultado em 12 de maio de 2021 
  15. «pepper.js Examples». Trypepperjs.appspot.com. Consultado em 12 de maio de 2021 
  16. «emscripten-qt — Demos». Vps.etotheipiplusone.com. Consultado em 12 de maio de 2021 
  17. «About Emscripten» 
  18. «Vim.js — JavaScript port of Vim». Coolwanglu.github.io. Consultado em 12 de maio de 2021 
  19. «TrueType Fonts in JavaScript». Consultado em 12 de maio de 2021. Cópia arquivada em 12 de outubro de 2012 
  20. «Port of SQLite to Javascript». Github.com. Consultado em 12 de maio de 2021 
  21. «GnuPG.js». Manuuels.github.io. Consultado em 12 de maio de 2021 
  22. «ctags in the browser». Github.com. Consultado em 12 de maio de 2021 
  23. «Gnuplot online». Gnuplot.respawned.com. Consultado em 12 de maio de 2021 
  24. «A hack to put GraphViz on the web.». Github.com. Consultado em 12 de maio de 2021 
  25. «JavaScript port of ZLib DEFLATE for the browser». Github.com. Consultado em 12 de maio de 2021 
  26. «Epic Games Releases 'Epic Citadel' on the Web». UnrealEngine.com (Nota de imprensa). 2 de maio de 2013. Consultado em 12 de maio de 2021. Arquivado do original em 30 de novembro de 2016 
  27. «Unreal Engine 3 ported to JavaScript and WebGL, works in any modern browser». ExtremeTech. Ziff Davis. Consultado em 12 de maio de 2021 
  28. «On the future of Web publishing in Unity». Blogs.unity3d.com. 29 de abril de 2014 
  29. «HTML5». Clb.demon.fi. Consultado em 12 de maio de 2021. Arquivado do original em 6 de março de 2015 
  30. «Compiling for the Web». godotengine.org. 10 de novembro de 2016 
  31. «Emscripten-Generated Code». Kripken.github.io. Consultado em 12 de maio de 2021 
  32. «Emscripten-Generated Code». Forandom.github.io. Consultado em 12 de maio de 2021 
  33. Guryanov Aleksander. «Dune 2 - Online (browser version)». Epicport. Consultado em 12 de maio de 2021 
  34. «Mozilla Banana Bread Demo». Developer.mozilla.org. Consultado em 12 de maio de 2021 
  35. «Humble Mozilla Bundle pushes WebGL-powered browser gaming». Ars Technica. 15 de outubro de 2014. Consultado em 12 de maio de 2021 
  36. «EM-Dosbox on Github». Consultado em 12 de maio de 2021 
  37. «Page Redirection». Jsmess.textfiles.com. Consultado em 12 de maio de 2021 
  38. «HTML5 Fractal Playground». Danielsadvernture.info. Consultado em 12 de maio de 2021. Arquivado do original em 22 de fevereiro de 2015 
  39. «FAQ». WebAssembly 
  40. «TC39 proposal for SIMD.js». Ecma TC39. 23 de junho de 2020 
  41. «WebAssembly/binaryen». GitHub. WebAssembly. 25 de junho de 2020. AssemblyScript which compiles TypeScript to Binaryen IR; wasm2js which compiles WebAssembly to JS 
  42. «Binaryen Changelog». GitHub (em inglês). v97: Remove asm2wasm, which supported Emscripten's fastcomp backend, after fastcomp was removed.  (Ver também PR#3042.)

Ligações externas