que - ¿Se puede convertir el JavaScript común en asm.js o solo para acelerar los idiomas de bajo nivel con tipado estático?
javascript lenguaje dinamico (7)
He leído la pregunta ¿Cómo probar y desarrollar con asm.js? , y la respuesta aceptada proporciona un enlace a http://kripken.github.com/mloc_emscripten_talk/#/ .
La conclusión de esa presentación es que " los lenguajes de tipo estático y especialmente C / C ++ se pueden compilar efectivamente en JavaScript ", por lo que podemos " esperar que la velocidad de C / C ++ compilado llegue a 2 veces más lento que el código nativo o mejor". , más tarde este año ".
Pero, ¿qué pasa con los lenguajes no tipificados de forma estática, como el propio JavaScript normal? ¿Se puede compilar en asm.js?
¿Se puede compilar JavaScript en asm.js?
En realidad, no, debido a su naturaleza dinámica. Es el mismo problema que cuando intenta compilarlo en C o incluso en el código nativo ; en realidad, tendría que enviar una VM con él para encargarse de esos aspectos no estáticos. Al menos, una VM así es posible:
js.js es un intérprete de JavaScript en JavaScript. En lugar de tratar de crear un intérprete desde cero, SpiderMonkey se compila en LLVM y luego emscripten traduce el resultado en JavaScript.
Pero si el código asmjs se ejecuta más rápido que el JS normal, entonces tiene sentido compilar JS en asmjs, ¿no?
No. asm.js es un subconjunto bastante restringido de JS que se puede traducir fácilmente a bytecode. Sin embargo, primero tendría que descomponer todas las funciones avanzadas de JS en ese subconjunto para obtener esta ventaja, una tarea bastante complicada. Pero los motores de JavaScript están diseñados y optimizados para traducir todas esas funciones avanzadas directamente en bytecode, así que ¿por qué preocuparse por un paso intermedio como asm.js? Js.js afirma ser 200 veces más lento que JS "nativo".
¿Y qué hay de los lenguajes no tipificados estáticamente en general?
La presentación de diapositivas habla de eso ... ¿Solo C / C ++? adelante. Específicamente:
Se pueden compilar todos los tiempos de ejecución de C / C ++ y se puede interpretar el lenguaje original con la semántica adecuada, pero no es liviano.
Los compiladores de fuente a fuente de dichos idiomas a JavaScript ignoran las diferencias semánticas (por ejemplo, los tipos numéricos)
En realidad, estos lenguajes dependen de máquinas virtuales especiales para ser eficientes
Los compiladores fuente-fuente para ellos pierden en las optimizaciones realizadas en esas máquinas virtuales
Algunos hechos sobre asm.js , que con suerte aclaran el concepto:
Sí, puedes escribir el dialecto asm.js a mano.
Si miras los ejemplos de asm.js , están muy lejos de ser fáciles de usar . Obviamente, Javascript no es el lenguaje de entrada para crear este código.
No es posible traducir el Javascript vainilla al dialecto asm.js.
Piénselo: si ya pudiera traducir el Javascript estándar de una manera totalmente estática, ¿por qué habría una necesidad de asm.js ? La única existencia de asm.js significa que las personas JavaScript JIT en algunas personas renunciaron a su promesa de que Javascript se volvería más rápido sin ningún esfuerzo por parte del desarrollador.
Hay varias razones para esto, pero digamos que sería muy difícil para el JIT entender un lenguaje dinámico tan bueno como un compilador estático. Y luego, probablemente, para que los desarrolladores comprendan completamente el JIT.
Al final, se reduce a usar la herramienta adecuada para la tarea. Si desea un código estático y de alto rendimiento, use C / C ++ (/ Java ); si desea un lenguaje dinámico, use Javascript , Python , ...
En respuesta a la pregunta general "¿es posible?" entonces la respuesta es que seguro, tanto JavaScript como el subconjunto asm.js están completos para que exista una traducción.
Si uno debe hacer esto y esperar un beneficio de rendimiento es una pregunta diferente. La respuesta corta es "no, no deberías". Yo comparo esto con tratar de comprimir un archivo comprimido; sí, es posible ejecutar el algoritmo de compresión, pero en general no debe esperar que el archivo resultante sea más pequeño.
La respuesta corta: el costo de rendimiento de los lenguajes de tipado dinámico proviene del significado del código; un programa de tipo estático con un significado equivalente tendría los mismos costos.
Para entender esto, es importante entender por qué asm.js ofrece un beneficio de rendimiento en absoluto; o, de manera más general, por qué los lenguajes de tipo estático funcionan mejor que los de tipo dinámico. La respuesta breve es "la verificación del tipo de tiempo de ejecución lleva tiempo" y una respuesta más larga incluiría la mejora de la viabilidad de optimizar el código de tipo estático. Por ejemplo:
function a(x) { return x + 1; }
function b(x) { return x - 1; }
function c(x, y) { return a(x) + b(y); }
Si se sabe que y
son enteros, puedo optimizar la función c
en un par de instrucciones de código de máquina. Si pueden ser enteros o cadenas, el problema de optimización se vuelve mucho más difícil; Tengo que tratar estos como cadenas anexas en algunos casos, y además en otros casos. En particular, hay cuatro posibles interpretaciones de la operación de suma que ocurre en c
; podría ser una adición, o un apéndice de cadena, o dos variantes diferentes de coerción a cadena y anexar. A medida que agrega más tipos posibles, crece la cantidad de permutaciones posibles; en el peor de los casos, para un lenguaje de tipo dinámico, tiene posibles interpretaciones de una expresión que involucre n términos que podrían tener cualquier número de k tipos. En un lenguaje estáticamente tipado, k = 1, entonces siempre hay 1 interpretación de cualquier expresión dada. Debido a esto, los optimizadores son fundamentalmente más eficientes para optimizar el código tipado estáticamente que el código de tipo dinámico: hay menos permutaciones que considerar al buscar oportunidades para optimizar.
El punto aquí es que al convertir de código de tipo dinámico a código de tipo estático (como lo estaría haciendo al pasar de JavaScript a asm.js), debe tener en cuenta la semántica del código original. Lo que significa que la verificación de tipo todavía se produce (ahora se ha escrito el código tipado estáticamente) y todas esas permutaciones siguen presentes para sofocar el compilador.
En teoría, es posible convertir / compilar / transpilar cualquier operación de JavaScript a asm.js si se puede expresar con el subconjunto limitado del lenguaje presente en asm.js. En la práctica, sin embargo, no existe una herramienta capaz de convertir JavaScript común a asm.js en este momento (junio de 2017).
De cualquier forma, tendría más sentido convertir un lenguaje con tipeo estático a asm.js, porque el tipado estático es un requisito de asm.js y la falta de eso es una de las características del JavaScript común que lo hace excepcionalmente difícil de compilar para asm. .js.
En 2013, cuando asm.js estaba caliente, hubo un intento de jlongster.com/Compiling-LLJS-to-asm.js,-Now-Available- , pero tanto el lenguaje como el compilador parecen haber sido abandonados.
Hoy, en 2017, los subconjuntos de JavaScipt TypeScript y Flow serían candidatos adecuados para la conversión a asm.js, pero los equipos de desarrollo central de ninguno de los dos idiomas están interesados en dicha conversión. jlongster.com/Compiling-LLJS-to-asm.js,-Now-Available- tenía un fork que podía compilar a asm.js, pero ese proyecto está prácticamente muerto. ThinScript es un intento mucho más reciente y está basado en TypeScript, pero tampoco parece estar activo.
Entonces, la mejor y más fácil forma de producir el código asm.js es escribir su código en C / C ++ y convertirlo / compilarlo / transpilarlo. Sin embargo, queda por verse si queremos hacer esto en el futuro previsible. Web Assembly pronto puede reemplazar asm.js por completo y ya aparecen lenguajes similares a TypeScript como TurboScript y AssemblyScript que se convierten a Web Assembly. De hecho, TurboScript se basó originalmente en ThinScript y se utilizó para compilar a asm.js, pero parecen haber abandonado esta característica.
Es posible convertir JavaScript regular en ams.js primero compilándolo en C o C++ , y luego compilando el código generado en asm.js usando Emscripten . No estoy seguro de si esto sería práctico, pero es un concepto interesante, no obstante.
asm.js ha sido creado por la necesidad de tener un pequeño subconjunto de javascript que se pueda optimizar fácilmente. Si puede tener una forma de convertir javascript a javascript / asm.js, asm.js ya no es necesario; ese método se puede insertar en intérpretes js directamente.
mira esto http://badassjs.com/post/43420901994/asm-js-a-low-level-highly-optimizable-subset-of
básicamente necesitas verificar que tu código sea compatible con asm.js (sin coerción o tipo de transmisión, necesitas administrar la memoria, etc.). La idea detrás de esto es escribir tu código en javascript, detectar el cuello de botella y hacer los cambios en tu código para usar asm.js y una compilación en vez de jit y compilación dinámica ... es un poco PITA pero aún puedes usar javascript u otro idiomas como c ++ o mejor ... en un futuro cercano, lljs .....