普通的JavaScript可以转换为asm.js,还是只能加速静态types的低级语言?

我读过这个问题如何用asm.jstesting和开发? ,接受的答案给出了链接http://kripken.github.com/mloc_emscripten_talk/#/ 。

幻灯片放映的结论是“ 静态types语言,尤其是C / C ++可以有效地编译为JavaScript ”,所以我们可以“ 期望编译的C / C ++的速度比本机代码慢2倍,或者更好,今年晚些时候 “。

但是非静态types的语言如常规的JavaScript本身呢? 它可以编译为asm.js吗?

JavaScript本身可以编译为asm.js吗?

不是真的,因为它的dynamic性。 当试图将它编译为C或者甚至是本地代码时,也是一样的问题 – 实际上您需要发送一个虚拟机来处理这些非静态的方面。 至less,这样的虚拟机是可能的:

js.js是JavaScript中的JavaScript解释器。 SpiderMonkey不是从头开始创build解释器,而是编译成LLVM ,然后emscripten将输出翻译成JavaScript。

但是,如果asmjs代码比普通的JS运行得更快,那么将JS编译成asmjs是有意义的,不是吗?

不, asm.js是JS的一个非常有限的子集,可以很容易地转换为字节码。 然而,你首先需要将JS的所有高级特性分解到这个子集来获得这个优势 – 这是一个非常复杂的任务。 但JavaScript引擎的devise和优化将所有这些高级特性直接转换为字节码 – 那么为什么还要为asm.js这样的中间步骤烦恼呢? Js.js声称比“本土”JS慢200倍左右。

一般来说,非静态types的语言呢?

幻灯片讲述从…只是C / C + +? 向前。 特别:

dynamic语言

整个C / C ++运行时可以被编译,并且原始的语言用适当的语义来解释,但是这不是轻量级的

从这种语言到JavaScript的源代码编译器会忽略语义差异(例如数字types)

实际上,这些语言依赖于特殊的虚拟机是有效的

这些源代码编译器在这些虚拟机上所做的优化工作中失败了

关于asm.js的一些事实,希望使这个概念清晰:

  1. 是的,你可以手写asm.js方言。

    如果你看过asm.js的例子,那么它们远不是用户友好的 。 Javascript显然不是创build这个代码的前端语言。

  2. 翻译香草JavaScript到asm.js方言是不可能的。

    想一想 – 如果你已经可以完全静态地翻译标准的Javascript,为什么会需要asm.js呢? asm.js的唯一存在意味着某些人的Javascript JIT人员放弃了他们的承诺:Javascript将会在没有开发人员的努力下变得更快。

    这有几个原因,但让我们只是说JIT理解dynamic语言和静态编译器一样好。 然后可能让开发者充分理解JIT。

最后归结为使用正确的工具来完成任务。 如果你想要静态的,性能非常好的代码,使用C / C ++ (/ Java ) – 如果你想要一个dynamic的语言,使用JavascriptPython ,…

针对一般性问题“是否有可能? 那么答案是肯定的,JavaScript和asm.js子集都是图灵完整的,所以存在翻译。

是否应该这样做,并期望performance的好处是一个不同的问题。 简短的回答是“不,你不应该”。 我把它比作试图压缩一个压缩文件; 是的,有可能运行压缩algorithm,但一般来说,你不应该期望得到的文件更小。

简短的回答:dynamictypes语言的性能成本来自代码的含义; 具有同等意义的静态types的程序将带来相同的成本。

为了理解这一点,了解asm.js 为什么提供性能优势是很重要的。 或者更一般地说,为什么静态types语言比dynamictypes语言performance更好。 简短的答案是“运行时types检查需要时间”,较长的回答将包括优化静态types代码的改进可行性。 例如:

function a(x) { return x + 1; } function b(x) { return x - 1; } function c(x, y) { return a(x) + b(y); } 

如果xy都是整数,我可以优化函数c给一些机器代码指令。 如果可以是整数或string,优化问题变得更加困难; 在某些情况下,我必须将它们作为string附加处理,而在其他情况下则另外添加。 特别是对c中出现的加法运算有四种可能的解释; 它可以是加法或string追加,也可以是强制到string和追加两种不同的变体。 随着您添加更多可能的types,可能的排列数量会增加; 在dynamictypes语言的最坏情况下,对于包含n个项的expression式可能有任意的解释,每个项可以有任意数量的k个types。 在一个静态types的语言中,k = 1,所以对任何给定的expression式总是有1个解释。 因此,与dynamictypes代码相比,优化器在优化静态types代码方面基本上更加高效:search优化机会时需要考虑的排列方式较less。

这里的要点是,当从dynamictypes代码转换为静态types代码时(就像从JavaScript到asm.js时所做的那样),您必须考虑原始代码的语义。 意味着types检查仍然发生(现在已经被拼写出静态types的代码),并且所有这些排列仍然存在以扼杀编译器。

asm.js已经创build了需要有一个小的子集的JavaScript,可以轻松优化。 如果您可以将JavaScript转换为javascript / asm.js,则不再需要asm.js – 该方法可以直接插入到js解释器中。

检查这个http://badassjs.com/post/43420901994/asm-js-a-low-level-highly-optimizable-subset-of

基本上你需要检查你的代码是否与asm.js兼容(没有强制或types转换,你需要pipe理内存等)。 这背后的想法是写你的代码在JavaScript中,检测瓶颈,并做你的代码的变化,使用asm.js和AOT编译,而不是JIT和dynamic编译…有点PITA,但你仍然可以使用JavaScript或其他像c + +或更好的语言..在不久的将来,lljs …..

通过首先将常规JavaScript 编译为C或C ++ ,然后使用Emscripten将生成的代码编译为asm.js,可以将常规JavaScript转换为ams.js。 我不确定这是否可行,但这是一个有趣的概念。

理论上,如果可以用asm.js中存在的语言的有限子集来表示,则可以将任何JavaScript操作转换/编译/传输到asm.js。 然而在实践中,目前没有能够将普通JavaScript转换为asm.js的工具(2017年6月)。

无论哪种方式,将静态types的语言转换为asm.js会更有意义,因为静态types是asm.js的一个要求,并且缺less普通JavaScript的特性之一,这使得编译为asm.jsexception困难.js文件。

早在2013年,当asm.js很热时,就试图编译类似于JavaScript的静态types语言 ,但是语言和编译器似乎都被抛弃了。

今天,到2017年,JavaScipt子集TypeScript和Flow将成为转换为asm.js的合适候选者,但是两种语言的核心开发团队都对这种转换感兴趣。 LLJS有一个可以编译成asm.js的分支,但是这个项目已经死了。 ThinScript是一个更近的尝试,并且基于TypeScript,但它似乎并不活跃。

所以,生成asm.js代码的最好和最简单的方法仍然是用C / C ++编写代码并转换/编译/传输它。 但是,我们是否希望在可预见的未来做到这一点还有待观察。 Web Assembly可能很快就会取代asm.js,并且已经出现了像TurboScript和AssemblyScript这样的TypeScript类语言,可以转换成Web Assembly。 事实上,TurboScript最初是基于ThinScript,用于编译为asm.js,但似乎已经放弃了这个function。