JIT-ed JavaScript比Java慢吗?

时间:2014-12-14 21:33:16

标签: javascript performance jit

JIT编译的JavaScript(比如V8引擎,因为它可能是最快的)执行速度比以前编译成字节代码的托管语言(例如Java或.NET语言)慢吗?

如果是 - 为什么?

我的意思是我理解JavaScript与字节代码相比需要更多的时间进行解析,但是在编译成机器代码后,它们应该同样表现良好,因为所有这些语言在功能上都相似......

2 个答案:

答案 0 :(得分:3)

首先,我想强调的是,没有办法给你这个问题的准确答案。可能存在这样的情况:在JIT VM上执行的JavaScript程序(如V8或SpiderMonkey)优于在JVM上执行的用Java编写的等效程序。当然,情况恰恰相反[1]。

其次,字节码本身不太可能对运行时性能产生任何重大影响。实际上,像HotSpot这样的现代JVM最终会将字节码转换为内部中间表示(IR)以实现优化的补充,就像V8对JavaScript源代码一样。

Java和JavaScript之间的关键区别在于类型信息的可用性(请注意,这是语言之间的根本区别,而不是它们的实现!)。由于Java是静态类型的,因此编译器在编译时知道每个变量*的类型。这意味着像a + b这样的表达式表示唯一操作(例如整数或浮点数加法),而在JavaScript中它也可能表示任何其他数量的其他事物(例如字符串连接) )。这意味着需要JavaScript JIT来生成代码以测试每种可能的正确和错误的类型组合,除非它能够以某种方式证明ab总是采用某些特定类型。

当然,问题不仅限于原始类型。例如,JavaScript表达式foo.bar应该评估什么?它取决于foo中值的类型,这在编译时是未知的;一个天真的实现将对象表示为哈希表,并在引用属性时执行查找(不用说,这会非常慢)。在Java中,如果foo是某个声明公共实例变量bar的类的实例,则编译器可以在内存中对象起始处的常量偏移处生成一个加载。

在当代JavaScript实现中似乎最普遍的补救措施是内联缓存(IC),这个概念在[2]中给出了比我希望提供的更好的解释。由于内联高速缓存可以用于收集可以提供给优化编译器的类型信息,因此只要出现在每个程序点的类型集很小且稳定,JavaScript程序完全可以赶上Java程序。

[1]有关几个例子,请参阅http://benchmarksgame.alioth.debian.org/u32/javascript.php。在撰写本文时,HotSpot在大多数基准测试中都击败了V8。

[2] http://mrale.ph/blog/2012/06/03/explaining-js-vms-in-js-inline-caches.html

(*)嗯,它知道每个变量的静态类型。当然,如果你的函数采用Object类型的参数,那么在JavaScript中作为无类型变量的推理几乎同样困难,但是可以在其上执行的操作集要小得多(例如,在Java中没有Object + Object

答案 1 :(得分:1)

为了简短起见,Javascript和Java是非常不同的语言。像Java / C#这样的静态类型编译语言在编译时有一个额外的优化步骤,并且生成的字节码已经针对目标体系结构进行了优化,如果你问我这是一个巨大的优势,并且它可以卸载运行时很多。

执行Javascript的引擎(例如V8或Chakra)必须在运行时做更多的事情,并且它们对对象的结构,预期的行为随着时间的推移以及内联,缓存等做了很多假设/猜测。执行优化要困难得多。动态性,多态对象的广泛使用和Javascript语言的其他功能在这里确实是一个问题。但是,如果你知道这些引擎的内部结构,你可以做很多事情来优化你的代码。

关于Javascript和Java之间的实际运行时性能,基准测试是您最好的朋友。正如@Elliot Frisch建议您可以选择一个示例算法并使用JS的V8命令行工具和Java的Java命令行进行测量。

您可能会发现,在某些情况下,V8执行的JS与Java(甚至是C ++)相对接近,但对于其他情况,它的速度要慢得多,而且这一切都取决于特定于代码的优化,即您要定位的特定运行时和其他因素。组合的数量很大,所以你找不到一个答案。