Chrome V8如何运作?为什么JavaScript最初不是JIT编译的?


19

我一直在研究解释器/编译器,然后偶然发现了JIT-Compilation-特别是Google Chrome的V8 Javascript Engine。

我的问题是-

  1. 怎么会比标准口译更快呢?
  2. 为什么不首先使用JIT-Compilation?


我目前的理解

  1. 每个Javascript程序都从源代码开始,然后不管执行方法如何,最终都将其翻译为机器代码
    无论JIT编译解释必须遵循这条道路,所以JIT编译怎么会有更快的(也因为JIT是有时间限制的,不像AOT编译)?

  2. 基于Wikipedia的JIT-Compilation Article,JIT-Compilation似乎是一个相对较旧的创新

“最早发布的JIT编译器通常归功于McCarthy在1960年对LISP的研究。”

“ Smalltalk(约1983年)开创了JIT编译的新方面。例如,按需转换为机器代码,并将结果缓存起来供以后使用。当内存不足时,系统将删除部分代码并重新生成再次需要它时。”

那么,为什么解释Javascript 开头呢?


我很困惑,对此我做了很多研究,但没有找到满意的答案。

如此简洁明了的答案将不胜感激。并且,如果需要引入有关解释器,JIT编译器等的更多解释,也将不胜感激。


2
#2和#3可以回答,但是“ Chrome V8 Engine如何工作?” 没有任何资格的范围太广;唯一正确的答案是V8源代码的链接。您是否要问有关V8的更多具体信息?(如果不是,最好删除一部分问题)
Ixrec 2015年

乍一看,我问#1的唯一目的就是要理解#2,因此我将其删除。感谢您的输入。
安东·帕拉斯,2015年

其他答案中未提及,但是JIT编译很困难。这不是一件容易的事,因为JIT编译导致的错误导致段错误而不是错误-程序崩溃而不是在控制台中引发错误。是的,对于一个熟练使用gdb的C程序员来说,这不是问题。但是几乎所有有能力使用gdb的合格C程序员都会得到报酬来从事其他项目。其他一些语言(例如Perl和Ruby)仍然没有主流的JIT解释器。
slebetman 2015年

如果您想知道。我是从编程语言的核心开发人员/维护人员的角度谈论这一问题。几年来,我被聘用来维护Ferite编程语言。我们的愿望清单之一是实施JIT。从来没有发生过-我们搬去了。多亏Facebook投入了足够的资金使PHP实现,PHP才刚刚获得了JIT编译器(HVVM)。
slebetman 2015年

Answers:


43

简短的答案是,JIT的初始化时间更长,但是从长远来看,它的速度要快得多,而JavaScript最初并不是为长期使用而设计的。

在90年代,网站上的典型JavaScript相当于标头中的一两个功能,以及少数直接嵌入onclick属性等中的代码。无论如何,当用户期望巨大的页面加载延迟时,它通常都能正确运行。考虑极基本的表单验证或小型数学实用程序,如抵押贷款利息计算器。

根据需要进行的解释要简单得多,并且可以为当天的用例提供完美的性能。如果您想要具有长期性能的产品,则可以使用Flash或Java Applet。

2004年的Google地图是首批大量使用JavaScript的杀手级应用程序之一。它对JavaScript的可能性大开眼界,但同时也突出了它的性能问题。Google花了一些时间来鼓励浏览器改善其JavaScript性能,然后最终决定竞争将是最好的动力,并且也将使他们在浏览器标准表中享有最佳席位。因此,Chrome和V8于2008年发布。现在,在Google Maps出现11年之后,我们有了新的开发人员,他们不记得JavaScript被认为不足以完成此类任务。

说你有一个功能animateDraggedMap。解释可能需要500毫秒,而JIT可能需要700毫秒来进行编译。但是,在JIT编译之后,实际运行可能只需要100毫秒。如果是90年代,而您只调用一次函数然后重新加载页面,JIT根本不值得。如果是今天并且您要调用animateDraggedMap数百次或数千次,则初始化时无需花费200毫秒,这可以在后台完成,甚至可以在用户尝试拖动地图之前完成。


2

通过了解运行时发生的情况,可以对代码或代码的解释进行更改,以使其比提前编译时可以更快地执行或更好地进行编译。

可以说,这是很多研究的主题。与理解差异:传统解释器,JIT编译器,JIT解释器和AOT编译器中给出的答案相比,我自己在这里的解释开始变得苍白。


简而言之,JavaScript最初并不是针对JIT进行编译或查找的,因为它绝不意味着任何复杂或重要的事情。

Java Script 的最初意图是链接到网页上的Java小程序。单击“ 从JavaScript代码调用Applet方法”可以看到单击某些按钮或在表单字段中输入值然后在Java applet方法中运行的能力。通过JavaScript,也有可能采用另一种从applet调用JavaScript代码的方式。

JavaScript的最初意图是链接小程序和包含小程序的html页面。对于这么小的任务,不需要很高的性能(如果需要性能,请调用JIT编写的applet方法)。

直到Netscape开始以JavaScript作为自己的语言来进行大量工作并促进其开发(包括Netscape Enterprise Server中的服务器端JavaScript-偶然地是在编译之前进行)之后,JavaScript才成为真正的目标。 。在那之后,花了很多年才能找到必要的工具来使其实用。


1
不,Javascript与Java不相关。Java applet是JVM字节码。
Basile Starynkevitch 2015年

@BasileStarynkevitch JavaScript旨在与小村庄页面中的Java小程序一起使用-充当html dom和Java对象中包含的方法之间的粘合剂。它不是,也从未打算成为Java。

JavaScript最初称为ECMAScript(或类似的名称),与Java无关。对于那些感兴趣的人,如何将其称为JavaScript是单独研究的主题。从此以后就引起了混乱。
quick_now

1
@quickly_now,现在仍然是tc39.github.io/ecma262
caub 2016年

是。出于某种奇怪的原因,当我指出以上内容时,我为此感到失望!
quick_now

1

JIT对于JavaScript是快速的,因为当您不知道变量的类型时,不可能生成快速的机器代码。

当您没有类型信息时,计算会很昂贵。例如,

x + y

如果您对x和y一无所知,则非常复杂。它们可能是整数,双精度数,字符串,甚至是此计算有副作用的对象。由于我们没有静态类型,因此这是一个昂贵的计算。

通过即时编译,我们可以使用运行时信息并将其转换为更快的计算。在运行时,V8会跟踪变量的类型。如果上面的代码用字符串执行了多次,则编译器可以执行更简单的字符串连接指令。因此,当编译器到达时x + y,而不是运行大量为许多不同类型的x和y分支的代码,而是编译器迅速检查我们是否再次具有字符串,然后仅执行几行专门连接字符串的机器代码。

例如,在C ++中,编译器会提前知道x和y的类型,因为我们必须声明变量。因此,它可以在运行代码之前生成优化的机器代码以连接字符串。


0

1)如何比标准口译更快? 好吧,一个深思熟虑的例子如下:假设我们有2个应用程序ApplicationCompiled和ApplicationInterpreted。这两个程序都做完全相同的事情,并且共享相同的源代码。ApplicationCompiled需要6秒钟的时间进行编译。

假设方案A的时间为:

  • 对于ApplicationCompiled:4秒
  • 对于ApplicationInterpreted:12秒

因此,总的来说,ApplicationCompiled需要10秒钟来运行方案A(6秒钟编译,需要4秒钟运行),而ApplicationInterpreted总共需要12秒钟才能运行。我没有具体的示例向您展示,并且我不确定在哪种情况下上述情况是正确的-它在很大程度上还取决于解释器和编译器的智能程度。

显然,这非常简化,但是可以将相同的想法应用于JIT编译/解释。接下来的问题是“我们如何以低成本确定该分支是否应通过JIT编译或解释”?我不在这里了:)

2)为什么不首先使用JIT-Compilation? 不知道,但我想这仅仅是资源和是否成熟的问题,这些困难在于使难于优化的语言(如JavaScript)应用诸如此类的先进技术的过程。当时可能有很多下垂的水果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.