我已阅读问题How to test and develop with asm.js?,接受的答案会提供http://kripken.github.com/mloc_emscripten_talk/#/的链接。
该幻灯片的结论是“静态类型语言,特别是C / C ++可以有效地编译成JavaScript ”,所以我们可以“期望编译C /的速度C ++比本机代码慢2倍,或者更好,今年晚些时候“。
但是非静态类型的语言呢,比如普通的JavaScript本身呢?可以编译为asm.js吗?
答案 0 :(得分:34)
JavaScript本身可以编译为asm.js吗?
不是真的,因为它的动态性。这与尝试编译to C甚至to native code时的问题相同 - 您实际上需要随身携带VM来处理这些非静态方面。至少,这样的VM是可能的:
js.js是JavaScript中的JavaScript解释器。而不是尝试从头开始创建解释器,SpiderMonkey被编译为LLVM,然后emscripten将输出转换为JavaScript。
但是如果asmjs代码比常规JS运行得更快,那么将JS编译为asmjs是否合理,不是吗?
没有。 asm.js是JS的一个非常有限的子集,可以很容易地转换为字节码。然而,您首先需要将JS的所有高级功能分解为该子集以获得此优势 - 这是一项非常复杂的任务。但JavaScript引擎经过精心设计和优化,可将直接的所有高级功能转换为字节码 - 所以为什么要打扰像asm.js这样的中间步骤呢? Js.js声称比“原生”JS慢大约200倍。
那么一般来说非静态类型的语言呢?
幻灯片从…Just C/C++?开始讨论这个问题。具体做法是:
可以编译整个C / C ++运行时和原始语言 用适当的语义解释,但这不是轻量级的
从这些语言到JavaScript的源到源编译器忽略 语义差异(例如,数字类型)
实际上,这些语言依赖于特殊的VM来提高效率
他们的源到源编译器会失去在这些虚拟机中完成的优化
答案 1 :(得分:12)
回答一般性问题“有可能吗?”然后答案是肯定的,JavaScript和asm.js子集都是Turing完成的,因此存在翻译。
是否应该这样做并期望获得性能优势是一个不同的问题。简短的回答是“不,你不应该。”我把它比作试图压缩压缩文件;是的,可以运行压缩算法,但一般情况下,您不应期望生成的文件更小。
简答:动态类型语言的性能成本来自代码的含义;具有相同含义的静态类型程序将承担相同的成本。
要理解这一点,重要的是要了解为什么 asm.js可以提供性能优势;或者,更一般地说,为什么静态类型语言比动态类型语言表现更好。简短的回答是“运行时类型检查需要时间”,更长的答案将包括优化静态类型代码的改进可行性。例如:
function a(x) { return x + 1; }
function b(x) { return x - 1; }
function c(x, y) { return a(x) + b(y); }
如果已知x
和y
都是整数,我可以将函数c
优化为几个机器代码指令。如果它们可以是整数或字符串,则优化问题变得更加困难;在某些情况下,我必须将这些视为字符串附加,并在其他情况下添加。特别是,c
中发生的加法运算有四种可能的解释;它可以是加法,或字符串追加,或强制转换为字符串和附加的两种不同变体。随着您添加更多可能的类型,可能的排列数量会增加;在最坏的情况下,对于动态类型语言,您有 k ^ n 对表达式的可能解释,涉及 n 术语,每个术语可以包含任意数量的 k < / em>类型。在静态类型语言中,k = 1,因此对任何给定表达式总是有1种解释。因此,优化器在优化静态类型代码方面比动态类型代码更有效:在搜索优化机会时需要考虑的排列更少。
这里的要点是,当从动态类型代码转换为静态类型代码时(就像从JavaScript转到asm.js时那样),您必须考虑原始代码的语义。这意味着仍然会发生类型检查(现在它已经拼写出静态类型的代码),并且所有这些排列仍然存在以扼杀编译器。
答案 2 :(得分:11)
关于 asm.js 的一些事实,希望能够明确这个概念:
是的,您可以手动编写 asm.js 方言。
如果您确实查看了 asm.js 的示例,那么它们远非用户友好。显然,Javascript不是创建此代码的前端语言。
将vanilla Javascript翻译为 asm.js 方言不可能。
考虑一下 - 如果您已经可以完全静态地翻译标准Javascript,为什么需要 asm.js ? asm.js 的唯一存在意味着某些人的Javascript JIT人员放弃了他们的承诺,即Javascript将在没有开发人员的任何努力的情况下变得更快。
这有几个原因,但我们只是说JIT理解动态语言和静态编译器一样真的很难。然后可能让开发人员完全理解JIT。
最后归结为使用正确的工具完成任务。如果您需要静态,高性能的代码,请使用 C / C ++ (/ Java ) - 如果您需要动态语言,请使用 Javascript , Python ,...
答案 3 :(得分:3)
asm.js是由需要有一小部分javascript创建的,可以轻松优化。如果你有办法将javascript转换为javascript / asm.js,则不再需要asm.js - 该方法可以直接插入js解释器中。
答案 4 :(得分:2)
理论上,如果可以使用asm.js中存在的有限语言子集表示,则可以将任何JavaScript操作转换/编译/转换为asm.js。然而,在实践中,目前(2017年6月)没有能够将普通JavaScript转换为asm.js的工具。
无论哪种方式,将带有static typing的语言转换为asm.js会更有意义,因为静态类型是asm.js的要求而缺少普通JavaScript的一个特性使其成为特别难以编译成asm.js。
早在2013年,当asm.js很热的时候,曾尝试compile a statically typed language similar to JavaScript,但语言和编译器似乎都已被抛弃。
今天,在2017年,JavaScipt子集TypeScript和Flow将适合转换为asm.js,但两种语言的核心开发团队都不会对此类转换感兴趣。 LLJS有一个可以编译为asm.js的fork,但该项目已经死了。 ThinScript是一项更近期的尝试,基于TypeScript,但它似乎也不活跃。
因此,生成asm.js代码的最佳和最简单的方法仍然是用C / C ++编写代码并转换/编译/转换它。然而,我们是否还想在可预见的未来做到这一点还有待观察。 Web Assembly可能很快就会取代asm.js,并且已经出现了类似TypeScript的语言,如TurboScript和AssemblyScript转换为Web程序集。实际上,TurboScript最初是基于ThinScript并用于编译为asm.js,但它们似乎已经放弃了这个功能。
答案 5 :(得分:1)
检查此http://badassjs.com/post/43420901994/asm-js-a-low-level-highly-optimizable-subset-of
基本上你需要检查你的代码是否与 asm.js 兼容(没有强制或类型转换,你需要管理内存等)。这背后的想法是在javascript中编写代码,检测瓶颈并在代码中进行更改以使用asm.js和aot编译而不是jit和动态编译...有点PITA但你仍然可以使用javascript或其他语言如c ++或更好......在不久的将来,lljs .....
答案 6 :(得分:1)
可以通过第一个compiling it into C或C++将常规JavaScript转换为ams.js,然后使用Emscripten将生成的代码编译为asm.js。我不确定这是否实用,但它仍然是一个有趣的概念。
最近,我发现了另一个名为NectarJS的工具,它将JavaScript编译为WebAssembly和ASM.js。