19

如果我不得不猜测,我很确定答案是 Clojure,但我不确定为什么。从逻辑上(对我来说)看起来 ClojureScript 应该更快:

两者都是“动态的”,但 ClojureScript

  • 编译为 JavaScript,在 V8 上运行
  • V8 引擎可以说是最快的动态语言引擎
  • V8 是用 C 编写的

而 Clojure:

  • 也是动态的
  • 在没有内置动态支持的 JVM 中运行,所以我认为 JVM 也必须做 V8 正在做的任何事情,以启用动态支持
  • 而且Java比C慢

那么 Clojure 怎么会比 ClojureScript 更快呢?当说 JavaScript 是动态的而 Clojure 是动态的时,“动态”是否意味着不同的东西?我没看到什么?

(当然如果 ClojureScript确实更快,那么上面的推理是否正确?)

我想,Clojure 编译成什么……至少是问题的一部分。我知道 JVM 部分不能只是一个普通的解释器(否则 ClojureScript 会更快),但 Clojure 不能编译为常规字节码,因为 JVM 中没有“动态”。那么 ClojureScript 的编译/执行方式与 Clojure 的编译/执行方式以及普通 Java 的编译/执行方式之间有什么区别,以及两者所隐含的性能差异?

4

3 回答 3

32

实际上,V8 是用 C++ 编写的。但是,它的功能与 JVM 基本相同,并且 JVM 是用 C 编写的。V8 JITs Javascript 代码并执行 JIT'd 代码。同样,JVM JIT 编译(或热点编译)字节码(不是 Java)并执行生成的代码。

字节码不像 Java 那样是静态的。事实上,它可以是非常动态的。另一方面,Java 大多是静态的,将 Java 与字节码混为一谈是不正确的。java编译器将Java源代码转换成字节码,JVM执行字节码。有关更多信息,我建议您查看 John Rose 的博客(示例)。那里有很多很好的信息。另外,尝试寻找 Cliff Click 的演讲(比如这个)。

同样,Clojure 代码直接编译为字节码,然后 JVM 使用该字节码执行相同的过程。编译 Clojure 通常在运行时完成,这不是最快的过程。同样,将 Clojurescript 翻译成 Javascript 也不是很快。V8 将 Javascript 转换为可执行形式显然非常快。Clojure 可以提前编译成字节码,这样可以消除很多启动开销。

正如您所说,说 JVM 解释字节码也不是很正确。17 年前的 1.0 版本就做到了!

传统上,有两种编译模式。第一种模式是 JIT(即时)编译器。字节码直接翻译成机器码。Java 的 JIT 编译执行速度很快,并且不会生成高度优化的代码。它运行正常。

第二种模式称为热点编译器。热点编译器非常复杂。它以解释模式非常快速地启动程序,并在程序运行时对其进行分析。当它检测到热点(代码中频繁执行的点)时,它会编译这些热点。而 JIT 编译器必须快速,因为除非它是 JIT 的,否则不会执行任何操作,热点编译器可以花费额外的时间来优化它正在编译的代码中的 snot。

此外,它可以稍后返回并重新访问该代码,并在必要和可能的情况下对其应用更多优化。这是热点编译器可以开始击败已编译的 C/C++ 的点。因为它具有代码的运行时知识,所以它可以应用静态 C/C++ 编译器无法进行的优化。例如,它可以内联虚函数。

Hotspot 还有另一个特性,据我所知,其他环境没有,它还可以在必要时对代码进行反优化。例如,如果代码不断地采用单个分支,并且该分支已经过优化并且运行时条件发生变化,迫使代码进入另一个(未优化的)分支,那么性能突然变得很糟糕。Hotspot 可以取消优化该功能并重新开始分析以找出如何使其更好地运行。

热点的一个缺点是它开始有点慢。Java 7 JVM 中的一项更改是结合了 JIT 编译器和热点编译器。这种模式是新的,虽然不是默认模式,但是一旦它初始启动应该是好的,然后它可以开始JVM非常擅长的高级优化。

干杯!

于 2012-12-11T03:24:15.693 回答
27

如果不参考特定的基准测试任务(甚至是特定版本的 Clojure 或 ClojureScript),这个问题很难准确回答。

话虽如此,在大多数情况下,我希望 Clojure 会更快一些。原因:

  • Clojure通常会编译成静态代码,因此它实际上不会在运行时进行任何动态查找。这一点非常重要:高性能代码通常会生成与静态类型 Java 非常相似的字节码。问题似乎是错误地假设动态语言必须在运行时进行动态方法查找:情况并非总是如此(通常不在 Clojure 中)
  • JVM JIT 设计得非常好,我相信它目前仍然比 JavaScript JIT 好一点,尽管 V8 有多好。
  • 如果您需要并发性或需要利用多核,那么显然没有竞争,因为 JavaScript 是单线程的......
  • Clojure 编译器比 ClojureScript 更成熟,并且近年来进行了大量的性能调优工作(包括原始支持、协议等)

当然,可以用任何语言编写快速或慢速代码。这将比语言实现之间的根本差异产生更大的差异。

更根本的是,您在 Clojure 和 ClojureScript 之间的选择在任何情况下都不应该与性能有关。两者都提供了引人注目的生产力优势。主要的决定因素应该是:

  • 如果你想在 web 上运行,请使用 ClojureScript
  • 如果要在 JVM 环境中的服务器上运行,请使用 Clojure
于 2012-12-11T04:07:31.750 回答
2

这与其说是一个历史评论,不如说是一个答案:HotSpot VM 和 V8 js 引擎都可以追溯到 Sun Microsystems 的 Self 项目,我认为该项目是许多技术的原型,使它们能够以同样快的速度运行就像他们一样。比较它们时要考虑的事情。我会将此作为评论发布,但声誉系统阻止了我。

于 2015-03-22T14:31:38.473 回答