Diseñada por | Mozilla |
---|---|
Apareció por primera vez | 21 de marzo de 2013 [1] |
SO | Plataforma independiente |
Sitio web | asmjs |
Influenciado por | |
JavaScript | |
Influenciado | |
WebAssembly |
asm.js es un subconjunto de JavaScript diseñado para permitir que el software de computadora escrito en lenguajes como C se ejecute como aplicaciones web mientras mantiene las características de rendimiento considerablemente mejores que el JavaScript estándar , que es el lenguaje típico utilizado para tales aplicaciones.
asm.js consiste en un subconjunto estricto de JavaScript, al cual el código escrito en lenguajes de tipado estático con administración manual de memoria (como C) es traducido por un compilador de fuente a fuente como Emscripten (basado en LLVM ). [2] El rendimiento se mejora al limitar las funciones del lenguaje a aquellas que se pueden optimizar con anticipación y otras mejoras de rendimiento.
Mozilla Firefox fue el primer navegador web en implementar optimizaciones específicas de asm.js, comenzando con la versión 22. [3]
asm.js es reemplazado por WebAssembly . Consulte § Desactivación a continuación.
asm.js permite mejoras significativas en el rendimiento de las aplicaciones web , pero no tiene como objetivo mejorar el rendimiento del código JavaScript escrito a mano, ni permite nada más que un rendimiento mejorado.
Está destinado a tener características de rendimiento más cercanas a las del código nativo que al JavaScript estándar al limitar las características del lenguaje a aquellas que se pueden optimizar con anticipación y otras mejoras de rendimiento. [4] Al utilizar un subconjunto de JavaScript, asm.js es ampliamente compatible con los principales navegadores web , [5] a diferencia de enfoques alternativos como Google Native Client .
Esta sección no cita ninguna fuente . ( Marzo de 2015 ) |
asm.js normalmente no se escribe directamente: en cambio, como lenguaje intermedio, se genera mediante el uso de un compilador que toma el código fuente en un lenguaje como C ++ y genera asm.js.
Por ejemplo, dado el siguiente código C:
int f ( int i ) { return i + 1 ; }
Emscripten generaría el siguiente código JS:
función f ( i ) { i = i | 0 ; retorno ( i + 1 ) | 0 ; }
Tenga en cuenta la adición |0
y la falta de especificadores de tipo. En JavaScript, los operadores bit a bit convierten sus operandos en enteros de 32 bits con signo y dan resultados enteros. Esto significa que un OR bit a bitcon cero convierte un valor en un número entero (una presentación "conceptual" muy simple de operadores bit a bit puede que no se ocupe de la conversión de tipos, pero cada lenguaje de programación define operadores para su propia conveniencia, como lo hace Javascript aquí). Al hacer esto para cada parámetro, esto asegura que si la función se llama desde un código externo, el valor se convertirá al tipo correcto. Esto también se utiliza en el valor de retorno, en este caso para garantizar que el resultado de sumar 1 a i será un número entero (de lo contrario, podría volverse demasiado grande) y para marcar el tipo de retorno de la función. Estas conversiones son necesarias para asm.js, de modo que un compilador optimizador pueda producir código nativo altamente eficiente con anticipación. En un compilador de optimización de este tipo, no se realizan conversiones cuando el código asm.js llama a otro código asm.js,ya que los especificadores de tipo requeridos significan que se garantiza que los valores ya tendrán el tipo correcto. Además, en lugar de realizar una suma de punto flotante y convertir a un número entero, simplemente puede hacer una operación nativa de números enteros. En conjunto, esto conduce a importantes beneficios de rendimiento.
Aquí hay otro ejemplo para calcular la longitud de una cadena:
size_t strlen ( char * ptr ) { char * curr = ptr ; while ( * curr ! = 0 ) { curr ++ ; } return ( curr - ptr ); }
Esto daría como resultado el siguiente código asm.js:
función strlen ( ptr ) { ptr = ptr | 0 ; var curr = 0 ; curr = ptr ; while (( MEM8 [ curr >> 0 ] | 0 ) ! = 0 ) { curr = ( curr + 1 ) | 0 ; } return ( curr - ptr ) | 0 ; }
En el código generado, la variable MEM8 es en realidad una "vista" byte por byte de un búfer escrito, que sirve como el "montón" del código asm.js.
Dado que asm.js se ejecuta en un navegador, el rendimiento depende en gran medida tanto del navegador como del hardware. Los puntos de referencia preliminares de los programas en C compilados en asm.js suelen tener un factor de desaceleración de 2 sobre la compilación nativa con Clang . [6]
Gran parte de esta ganancia de rendimiento sobre JavaScript normal se debe al 100% de la coherencia de tipos y prácticamente a la ausencia de recolección de basura (la memoria se administra manualmente en una gran matriz de tipos ). Este modelo más simple sin comportamiento dinámico, sin asignación o desasignación de memoria, solo un conjunto estrecho de operaciones enteras y de coma flotante bien definidas permite un rendimiento y un potencial de optimización mucho mayores . [ cita requerida ]
El benchmark de Mozilla de diciembre de 2013 mostró mejoras significativas: "Firefox con optimizaciones float32 puede ejecutar todos esos benchmarks alrededor de 1,5 veces más lento que el nativo, o mejor". [7] Mozilla señala que el rendimiento del código compilado de forma nativa no es una medida única sino más bien un rango, con diferentes compiladores nativos (en este caso Clang y GCC ) entregando código de diferente rendimiento. "De hecho, en algunos puntos de referencia, como Box2D , FASTA y copy, asm.js está tan cerca o más cerca de Clang que Clang de GCC. En un caso, asm.js incluso supera a Clang por una pequeña cantidad en Box2D". [7]
El proyecto Emscripten proporciona herramientas que se pueden utilizar para compilar bases de código C y C ++ (o cualquier otro lenguaje que se pueda convertir a LLVM IR ) en asm.js. [2]
Todos los navegadores compatibles con ECMAScript 6 deberían poder ejecutar código asm.js, ya que es un subconjunto de esa especificación. Sin embargo, dado que se agregaron características en esa edición para habilitar el soporte completo de asm.js ( Math.fround()
), los navegadores más antiguos que carecen de esas características pueden encontrar problemas.
Algunas implementaciones del navegador están especialmente optimizadas para asm.js:
Esta sección se basa demasiado en referencias a fuentes primarias . ( Marzo de 2015 ) |
Casi todas las aplicaciones actuales basadas en asm.js son aplicaciones C / C ++ compiladas en asm.js usando Emscripten o Mandreel. Con eso en mente, el tipo de aplicaciones que se dirigirán a asm.js en un futuro cercano son aquellas que se beneficiarán de la portabilidad de ejecutarse en un navegador, pero que tienen un nivel de complejidad para el que sería un puerto directo a JavaScript. inviable.
Hasta ahora, ya se han adaptado varios lenguajes de programación , marcos de aplicaciones , programas , bibliotecas , juegos , motores de juegos y otro software . [10] Algunos de ellos se dan a continuación.
asm.js se vuelve obsoleto en su mayoría con la introducción de WebAssembly (wasm), que tiene un formato de código de bytes que es más rápido de analizar. [40] Los esfuerzos para extender JavaScript con más funciones de bajo nivel como SIMD.js también se suspendieron desde 2017. [41]
asm.js sigue siendo útil principalmente como un "respaldo" para wasm, a través de un programa escrito por la organización WebAssembly que convierte wasm en asm.js. No hay un convertidor dedicado de asm.js a wasm, pero los compiladores TypeScript -to-wasm se pueden usar parcialmente. [42] El binaryen emisor de WebAssembly de referencia solía contener un asm2wasm
módulo, pero se eliminó después de que Emscripten dejó de usarlo. [43]
AssemblyScript que compila TypeScript en Binaryen IR;
wasm2js que compila WebAssembly en JS
v97: Elimine asm2wasm, que era compatible con el backend fastcomp de Emscripten, después de que se eliminó fastcomp.(Consulte también el PR # 3042 ).