JavaScript 引擎和 Just-in-Time 编译概念,Hot Function 的简单介绍

简介: JavaScript 引擎和 Just-in-Time 编译概念,Hot Function 的简单介绍

JavaScript 引擎本身也是一种软件,它将您华丽的 JavaScript 代码行转换为我们的机器可执行的二进制代码。


image.png


所有主要浏览器都开发了自己的 JavaScript 引擎。 Chrome 有 V8,Firefox 运行 SpiderMonkey(第一个 JavaScript 引擎的进化产品,由 Brendan Eich 在 90 年代为 Netscape Navigator 开发),Microsoft Edge 有 Chakra,Safari 有 Nitro。 Node.js 建立在 Chrome 的 V8 引擎之上。 物联网设备也可以有一个 JavaScript 引擎。


每个 JavaScript 引擎都负责使用 Ecma International 的 TC39 制定的 ECMAScript 规则和标准。


Why modern JavaScript engines do Just-In-Time compilation

JavaScript 是一门动态类型语言。

image.png

这意味着无论何时你在 JavaScript 中声明一个变量,你都不必明确说明变量 x 存储的信息类型。 JavaScript 引擎在执行源代码时检查类型。


在静态类型语言(如 C++)中声明变量时,您必须显式指定变量值的类型。

image.png

有了如此严格的规则,静态类型语言可以具有更高的学习曲线。在尝试编写一个简单的程序之前,您必须更多地了解它的规则和类型。


然而,从编译器的角度来看,静态类型语言允许更快的性能。预先,当编译器开始将代码转换为可执行的机器代码二进制时,该语言为编译器提供了大量有关源代码的信息。


另一方面,像 JavaScript 这样的动态类型语言很少向编译器提供有关其类型的信息。这为编译器在生成机器代码之前创建了另一层工作,使其执行速度比静态编写语言的编译慢。


But fear not, this is where Just-In-Time compilation comes in!

最初开发 JavaScript 时,它旨在编写少量用于增强网页的脚本。随着开发人员开始构建和使用更多 JavaScript 框架和库,以及发出 AJAX 请求,对更好、更快性能的需求不断增长。


当 Chrome 于 2008 年推出时,谷歌还首次发布了其 V8 引擎,这是现代 JavaScript 引擎中的第一个。 V8 的主要特性之一是即时编译 - Just-In-Time compilation。


在 Ahead-of-Time 编译中,编译过程必须在系统运行可执行机器代码之前完成。有了 Just-In-Time compilation 这一新特性,V8引擎会根据需要编译源代码,在执行编译过程生成的机器码时收集类型信息,然后根据执行过程收集的信息重新编译源代码。两个进程之间的来回加快了执行过程的性能。


为了让 JavaScript 在动态类型的情况下仍能以最快的速度运行,JavaScript 引擎有一些巧妙的技巧。


像大多数现代 JavaScript 引擎一样,V8 有两个编译器:基线 (baseline)编译器和优化编译器。


当 V8 编译你的 JavaScript 代码时,它的解析器会生成一种叫做抽象语法树的东西。Ignition,V8 的基线编译器或解释器,从这个语法树生成字节码。 Ignition 忠实于它的即时编译特性,它编译 JavaScript 代码,运行它,编译它,运行它,来回,一遍又一遍。


在运行时,字节码被分析,引擎识别可以重新编译以获得最佳性能的部分(“热函数”),将该代码发送到 TurboFan,它是 V8 的优化编译器。正是因为即时编译,引擎才能够因为即时编译而识别这些所谓的“热功能”。

image.png



The + operator and V8 optimization

在她的精彩演讲 JavaScript 引擎中,V8 工程师 Franziska Hinkelmann 使用 + 运算符来解释 V8 的优化是如何工作的。


乍一看,加法运算符可能看起来很简单,任何编译器都可以编译和执行。 但是,如果您查看 Ecma 规范,在程序实际添加任何内容之前,引擎实际上需要执行很多步骤:


image.png


这些步骤中的每一步都在调用其他函数,而这些函数又可能调用其他函数,依此类推。所有引擎都必须遵循这些 Ecma 规范,因此 JavaScript 不仅仅是无法无天的。


因此,当您的程序有一个将两个整数相加的函数时,当您第一次调用该函数时,JavaScript 引擎会费力地完成这些步骤中的每一步,最终将您的两个整数相加。当它通过 JIT 过程(编译、运行、编译、运行、编译等)时,它意识到你的函数很热,很热,很热,因为你一直在调用它。从引擎在运行时收集的信息,它也意识到这个特定函数使用的数据类型只是整数。有了这些信息,V8 将您的代码发送到 TurboFan,它的优化器编译器,它为您的函数生成更好的机器代码。下次您再次调用该函数时,它会跳过冗长的 Ecma 步骤,您的函数将运行得更快。


但是当您决定在调用该函数时连接一些字符串而不是添加两个整数时会发生什么? V8 将该函数抛出到去优化器,将其发送回 Ignition,然后 Igntion 再次执行那些 Ecma 指定的步骤来运行该函数。


相关文章
|
2月前
|
资源调度 前端开发 JavaScript
Babel:JavaScript代码的编译利器
Babel:JavaScript代码的编译利器
|
25天前
|
JavaScript 前端开发 开发者
JavaScript的变量提升是一种编译阶段的行为,它将`var`声明的变量和函数声明移至作用域顶部。
【6月更文挑战第27天】JavaScript的变量提升是一种编译阶段的行为,它将`var`声明的变量和函数声明移至作用域顶部。变量默认值为`undefined`,函数则整体提升。`let`和`const`不在提升范围内,存在暂时性死区。现代实践推荐明确声明位置以减少误解。
23 2
|
1月前
|
设计模式 JavaScript 前端开发
在JavaScript中,继承是一个重要的概念,它允许我们基于现有的类(或构造函数)创建新的类
【6月更文挑战第15天】JavaScript继承促进代码复用与扩展,创建类层次结构,但过深的继承链导致复杂性增加,紧密耦合增加维护成本,单继承限制灵活性,方法覆盖可能隐藏父类功能,且可能影响性能。设计时需谨慎权衡并考虑使用组合等替代方案。
36 7
|
1月前
|
JSON JavaScript 前端开发
【JavaScript】JavaScript中的深拷贝与浅拷贝详解:基础概念与区别
JavaScript 中,理解数据拷贝的深浅至关重要。浅拷贝(如扩展运算符`...`、`Object.assign()`)仅复制对象第一层,共享内部引用,导致修改时产生意外联动。深拷贝(如自定义递归函数、`_.cloneDeep`或`JSON.parse(JSON.stringify())`)创建独立副本,确保数据隔离。选择哪种取决于性能、数据独立性和资源需求。深拷贝虽慢,但确保安全;浅拷贝快,但需小心引用共享。在面试中,理解这些概念及其应用场景是关键。
37 4
【JavaScript】JavaScript中的深拷贝与浅拷贝详解:基础概念与区别
|
25天前
|
XML 缓存 JavaScript
一篇文章讲明白JS模板引擎之JST模板
一篇文章讲明白JS模板引擎之JST模板
16 2
|
26天前
|
存储 JSON 前端开发
JavaScript 进阶征途:解锁Function奥秘,深掘Object方法精髓
JavaScript 进阶征途:解锁Function奥秘,深掘Object方法精髓
|
27天前
|
JavaScript 前端开发
JavaScript函数核心概念:用于代码复用与管理。
【6月更文挑战第25天】JavaScript函数核心概念:用于代码复用与管理。示例包括定义(无参、有参、有返回值)与调用,参数按值传递。函数内修改参数不影响外部变量。
14 1
|
1月前
|
JavaScript 前端开发
JavaScript函数是代码复用的关键。使用`function`创建函数
【6月更文挑战第22天】JavaScript函数是代码复用的关键。使用`function`创建函数,如`function sayHello() {...}`或`function addNumbers(num1, num2) {...}`。调用函数如`sayHello()`执行其代码,传递参数按值进行。函数可通过`return`返回值,无返回值默认为`undefined`。理解函数对于模块化编程至关重要。
24 4
|
1月前
|
缓存 自然语言处理 前端开发
深入剖析JavaScript引擎的工作原理
【6月更文挑战第3天】JavaScript引擎由解析器、解释器、优化器和垃圾回收器组成,它们协同完成代码的解析、编译和执行。解析器将源代码转为抽象语法树(AST),编译阶段进行作用域分析和变量提升。解释器执行AST,优化器在代码频繁执行时进行即时编译以提高性能。垃圾回收器自动回收不再使用的内存,防止泄漏。理解这些原理有助于优化代码和提升Web应用性能。
20 1
|
2月前
|
JavaScript 前端开发 NoSQL
【MongoDB 专栏】MongoDB 的 JavaScript 引擎与脚本执行
【5月更文挑战第11天】MongoDB 的 JavaScript 引擎允许在服务器端直接执行脚本,提升效率并实现定制化操作。脚本环境提供独立但与数据库关联的运行空间,引擎负责脚本的解析、编译和执行。执行过程包括脚本提交、解析、编译和执行四个步骤。掌握脚本逻辑设计和 JavaScript 语言特性对于高效利用这一功能至关重要。例如,通过脚本可以计算商品总销售额,增强数据库操作的灵活性。
【MongoDB 专栏】MongoDB 的 JavaScript 引擎与脚本执行

热门文章

最新文章