27

详解JavaScript引擎的相关概念和工作原理

 3 years ago
source link: http://developer.51cto.com/art/202010/630261.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

R36v6rz.jpg!mobile

【51CTO.com快译】朋友,您在编译和执行代码时,是否曾考虑过JavaScript背后的引擎?作为一名程序员,我建议您通过本文来了解JavaScript引擎的工作原理。这将有益于您编写出更加流畅且高质量的JavaScript代码。

什么是JavaScript引擎?

JavaScript引擎遵循的是ECMAScript标准。此类标准定义了JavaScript引擎的工作机制和所有功能。因此,JavaScript引擎是一个程序,它可以帮助您将JavaScript代码转换为较低级别的机器代码。

总的说来,诸如JavaScript和FORTRAN等高级语言都是从机器语言中抽象出来的。与C或C++相比,JavaScript的抽象程度更高。而C和C++更接近于硬件,因此运行效率也会更高一些。

编译(compilation)与解释(interpretation)

编程语言通常通过编译(compilation)和解释(interpretation)来实现代码的功能。其中,

  • 编译器可以被定义为协助转换代码的程序。它可以将由任何编程语言(源语言)所编写的代码,转换为另一种目标语言的代码。例如:将源代码从高级编程语言转换为低级编程语言(即机器语言),来执行既定的任务。
  • 而解释器则是通过逐行、逐条指令地分析源代码,在无需第三方参与的情况下,直接在目标机器上执行相应机器代码。

尽管编译和解释是完成编程语言的两个方面,但是由于使用解释的大多数系统都需要由编译器完成的翻译工作,因此在某些情况下两者之间是存在交集的。就JavaScript而言,其技术上的编译,也属于解释类别。也就是说,JavaScript编译器在运行的时候,其执行的就是Just-In-Time(JIT)编译。在此,JavaScript引擎恰好可以连接到浏览器和Node JS之类的Web服务器,以便用户具有运行时(run-time)编译、以及执行JavaScript代码的权限。

JavaScript引擎剖析

ECMA脚本通过指定浏览器实施JavaScript的过程,以便程序在每个单一浏览器中都能运行一致。当然,每个浏览器都为提交过的JavaScript代码提供了一个运行所需的JavaScript引擎。例如:Netscape浏览器使用的是Spider Monkey JavaScript引擎。该引擎被定义为带有零优化(zero optimizations)的基本解释器。它虽然可以运行提交过来的JavaScript代码,但是耗时较长。

工作原理

JavaScript引擎工作的基本工作流程是:获取JavaScript源代码,然后使用易于CPU理解的二进制指令(机器代码)进行编译。

JavaScript引擎主要由基线编译器组成,该编译器以中间表示(intermediate representation,IR)的形式编译代码。换言之,它被字节码所调用,然后将字节码提供给解释器。解释器使用字节代码,将代码转换为机器代码,以适合在硬件上运行。其实,这与Java的工作原理非常相似,只不过字节代码的生成是由程序员完成的,而字节代码则可以被普遍共享。

虽然基线编译器的使命是尽可能快地执行代码编译,但是它还是会生成未经优化的字节码。在解释器中,这些字节码会导致应用程序的速度变慢。为此,Mozilla Firefox浏览器将Spider Monkey JavaScript进行了嵌入,以优化并提高机器代码的效率。例如:JavaScript引擎会直观地了解到变量的数据类型,进而更好地生成少量的机器代码。

此外,JavaScript引擎还可以根据代码的执行情况,通过收集和分析数据,发现代码运行缓慢的原因,进而给出优化并替换的建议。

知名的JavaScript引擎

除了前面介绍过Firefox正在使用的Spider Monkey引擎,还有Internet Explorer正在使用的Chakra引擎,而Google使用的是V8引擎。虽然它们用到了不同的编译器,但是它们所遵循的优化结构是相似的。

Google的V8:

由Lark Bak创建的The Chromium项目开发了开源的Javascript引擎。该项目为Google Chrome和Chromium网络浏览器提供了开发服务。Chrome的V8引擎几乎是在Chrome的首个版本诞生(2008年9月2日)的同时,就应运而生了。V8能够很好地兼容Node.js和 MongoDB 等服务器端技术。

由于V8带有Ignition解释器,因此它能够通过低级字节码完成解释与执行。尽管这些低级字节码比起机器码来说既小又慢,但它们需要编译的时间会更少。我们可以使用Full-Codegen编译器,来生成未优化的代码。该编译器的运行速度比其他编译器要快一些。JIT编译器—Turbofan不但可以编译代码,并且能够密切注意代码是否会在整个JavaScript执行的过程中被多次用到。也就是说,它的垃圾收集器会观察各种对象中不再引用到的数据。而且这种数据的收集工作是由收集器来完成的。值得一提的是,在执行垃圾回收的周期内,V8引擎将会自动停止程序的运行。

CHAKRA:

由Microsoft开发的Chakra JavaScript引擎,被用在了Microsoft Edge Web浏览器中。它是Internet Explorer中Jscript引擎的一个分支。我们可以简单地理解为:Chakra提高了Internet Explorer中JavaScript的执行质量。由于是用新的JavaScript编译器组成,因此Chakra可以帮助用户将JavaScript代码编译成为高级机器代码。通过提供全新的解释器,Chakra不但能够在传统的网页上执行脚本,而且能够改进JavaScript的运行时和各种库。

SPIDER MONKEY:

由Netscape Communications的Brendan Eich使用C和C++语言编写的Spider Monkey,最终被发布成为了开源的JavaScript引擎。目前,它被用在包括Firefox在内的许多享有Mozilla公共许可证(2.0版)的产品中。它将类型推断(type inference)与JIT编译器—Jaegermonkey相连接,以生成有效的代码。

在结构上,Spider Monkey是由一个解释器、几个JIT编译器、一个反编译器、以及一个垃圾收集器所组成。

RHINO:

由Mozilla Foundation管理的Rhino JavaScript引擎,是一款完全由Java编写的开源软件。它同样可以被使用在Mozilla Firefox中。

JavaScript运行时

与其他编程语言不同的是,JavaScript是一种单线程的语言运行时(language runtime),且只能一次性执行并完成程序代码。由于代码是按照顺序被执行的,因此那些需要花费较长时间的代码,可能会阻塞后续有待执行的其他代码。例如:当您在浏览器(如:Google Chrome)上打开某个网站时,它会调用JavaScript的一个执行线程,用来处理诸如滚动网页,在网页上打印部分内容,侦听DOM事件,以及执行某项操作等。然而,如果JavaScript一旦停止执行,浏览器就会自动停止所有各项操作。这就意味着浏览器在完成某项任务之前,并不会响应其他的任何内容。

根据概念,JavaScript运行时是指JavaScript代码所处的环境或条件。因此,当JavaScript在Google Chrome上执行时,JavaScript运行时便是v8;如果在Mozilla上,它就是Spider Monkey;如果在IE上,则为Chakra。

JavaScript运行时的API提供了一种执行桌面与服务器端应用的方法。由于这些API在Windows 10和任何版本的Windows操作系统上可用,因此Windows操作系统可以通过使用Chakra的相关标准,向应用程序添加不同的脚本功能。当然,目标系统上也需要安装好Internet Explorer 11。

内联缓存(Inline Caching)

内联缓存的概念源于经验观察。也就是说,通过观察并记住以前直接在调用站点处那些相同方法的查询结果,来加快运行时方法的绑定速度,并提高查找的性能。同时,为了简化此过程,我们可以为调用站点分配不同的状态。例如:将最初的站点分配为“未初始化(uninitialized)”状态。那么,语言运行时到达未初始化的特定调用站点时,将执行动态查找,并将结果存储到调用站点中,同时将其状态更改为“单态(monomorphic)”。后续,如果语言运行时再次到达同一调用站点时,它会从现有的存储中进行检索,并直接予以调用,而无需再次执行任何其他的查找。此外,为了解决不同类型的对象可能出现在同一调用站点的可能性,语言运行时还必须在代码中插入保护条件(guard conditions)。

至此,希望您已经对JavaScript引擎的相关概念和工作原理有所了解。希望您能更好地将其运用到项目编程中。

原文标题:How JavaScript Engine Works?,作者:Vyom Srivastava

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】

【责任编辑:庞桂玉 TEL:(010)68476606】


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK