我现在对JavaScript引擎感到困惑。我知道V8非常重要,因为它将JavaScript编译为本地代码。
然后我开始阅读关于Mozilla SpiderMonkey的文章,据我所知,它是用C编写的,并且可以编译JavaScript。那么这与V8有什么不同,如果是这样的话,为什么Firefox不这样做呢?
最后,Rhino是否真正将JavaScript编译为Java字节码,以便您能获得Java的所有速度优势? 如果不是,为什么人们不在桌面上运行V8来编写脚本?
我现在对JavaScript引擎感到困惑。我知道V8非常重要,因为它将JavaScript编译为本地代码。
然后我开始阅读关于Mozilla SpiderMonkey的文章,据我所知,它是用C编写的,并且可以编译JavaScript。那么这与V8有什么不同,如果是这样的话,为什么Firefox不这样做呢?
最后,Rhino是否真正将JavaScript编译为Java字节码,以便您能获得Java的所有速度优势? 如果不是,为什么人们不在桌面上运行V8来编写脚本?
在执行 JavaScript 时有各种方法,即使在进行 JIT 时也是如此。V8 和 Nitro (之前称为 SquirrelFish Extreme) 选择使用整体方法 JIT,这意味着它们在遇到脚本时会将所有 JavaScript 代码编译成本地指令,然后简单地执行它,就像执行已编译的 C 代码一样。而 SpiderMonkey 则采用“跟踪”JIT,首先将脚本编译为字节码并解释执行,但监视执行,寻找“热点”(如循环)。当检测到一个热点时,它会将该热路径编译为机器码,并在将来执行。
这两种方法都有优点和缺点。整体方法 JIT 确保所有执行的 JavaScript 都将被编译为机器代码而不是解释,通常应该更快。但是,根据实现,这可能意味着引擎花费时间编译永远不会被执行或只执行一次的代码,且性能不关键。此外,必须将编译后的代码存储在内存中,因此这可能导致更高的内存使用率。
SpiderMonkey 中实现的跟踪 JIT 可以与整体方法 JIT 相比产生极其专业化的代码,因为它已经执行了代码并可以推测变量的类型(例如将 for 循环中的索引变量视为本机整数),而整体方法 JIT 必须将变量视为对象,因为 JavaScript 是无类型的,类型可能会更改 (如果假设失败,SpiderMonkey 将简单地“跳出”跟踪并返回解释字节码)。然而,SpiderMonkey 的跟踪 JIT 目前在具有许多分支的代码上效率不高,因为跟踪是针对单一执行路径进行优化的。此外,在决定编译跟踪之前,监视执行需要一些开销,并且要切换到该跟踪的执行也会带来一些开销。此外,如果追踪程序做出后来被违反的假设(如变量更改类型),则从跟踪中退出并切换回解释的成本很可能比使用整体方法 JIT 更高。
V8是最快的,因为它将所有JS编译成机器码。
SpiderMonkey(FF使用的引擎)也很快,但它编译为中间字节码而不是机器码。这是与V8的主要区别。编辑 - 较新的Firefox版本配备了较新的SpideMonkey变体; TraceMonkey。TraceMonkey对关键部分进行JIT编译,可能还有其他智能优化。
Rhino将Javascript编译成Java类,从而允许您基本上用Javascript编写“Java”应用程序。Rhino还用作在后端解释JS并操作它以及具有完全代码理解(如反射)的一种方式。例如,YUI压缩器就是使用它。
之所以在大多数地方使用Rhino而不是V8,可能是因为V8相对较新,因此许多项目已经在使用Rhino / Spidermonkey作为其JS引擎,例如Yahoo小部件。 (我假设这就是您所指的“桌面上的脚本”)
编辑-此链接还可以提供一些有关为什么如此广泛采用SpiderMonkey的见解。 Which Javascript engine would you embed in your application?
如果您拥有Java和rhino jar,使用Rhino编写脚本非常容易,您只需编写JavaScript并从命令行运行即可。我经常用它来完成简单的任务。
V8 和 SpiderMonkey 都支持多通道编译和单通道编译。
Java Rhino 已经被弃用,并被一个名为 Truffle Framework 的新概念所取代,它是 GraalVM Stack 的一部分,实际上是添加到 JVM 中的 JVMCI,其中 CI 表示 Compiler Interface。这允许 Truffle 语言实现框架在 MultiPass 和 Single Pass 中实现任何语言并将其转换为 Java 字节码。ECMAScript 实现称为 GraalJS,有两种风味。
GraalJS 是 1:1 Rhino 替代品,包括增量采用的兼容模式和 graal-node,其中 v8 被 GraalJS 引擎替换的 NodeJS Fork。
正如所说,Truffle 是一个 Polyglot 语言实现框架,因此可以使用任何 GraalVM 支持的语言。
希望这有所帮助并且有些意义,因为当整个堆栈具有对齐版本时,jar 版本才能发挥最佳作用,您应该始终安装完整的堆栈:
https://github.com/graalvm/graalvm-ce-builds/releases
下载并安装,然后使用所谓的gu命令添加GraalJS,请按照此处的说明操作:https://github.com/oracle/graaljs
是的,GraalVM通常可以编译所有Polyglot语言的单个二进制可执行文件,这称为AOT编译,它具有更快的启动时间但吞吐量较低,它还可以进行JIT,并且可以混合使用两者。