原文:Parsing in V8 explained

本文档介绍了 V8 引擎是如何解析 JavaScript 源代码的,以及我们将改进它的计划。

动机

我们有个解析器和一个更快的预解析器(~2x),但是预解析器对大多数现代 JavaScript 无用。此外假如还没有编译了外部函数,否则我们必须再解析一遍内部函数。 那现在的 V8 引擎什么时候会立即编译(eager compilation)呢?

  1. 顶层的括号函数(function...

  2. 在 ( 之后的不是函数声明的内部函数

当我们把一个内部函数当做非脚本级的一部分来解析的时候,是不能使用预解析器的。我们将不会编译一个内部函数,所以如果我们永远不先行编译函数,那么一般的 n 层嵌套函数会先被预解析,然后会有 n 次解析(以及一次编译)。或从另一方面来看待它,考虑了以下格式的顶级“模块”:

!function f() {
function A() {
function B() {...}
}
function C() {
function D() {...}
}
...
}(), function g() {....}()

压缩程序经常用 (function() {...})();(function(){...}))() 替换上面的代码。但是,你可以看到它没有被括号括起来,所以我们不会在顶层运行完整的解析器。这是为什么呢?因为我们不知道这些函数会被立即调用。因此会使用更快的预解析器。但是确实需要这些函数,这就打脸了,而 V8 就不得不去再解析。预解析阶段会将整个顶层函数看一遍,包括 A, B, C, D(假如原本的 (function f() {...})() 编译过那么就会跳过本阶段)。

因为顶层函数被调用了,所以引擎会去解析它。这次解析是完全的。为什么呢?因为需要做范围解析以便知道在哪里分配变量。而唯一的正确的方式是知道什么变量被引用了。而知道什么变量被引用的唯一方式是对内部函数也进行完全的解析。所以解析/编译顶层函数会迫使引擎对 A,B,C,D 这些函数也进行完全解析。

现在我们需要调用函数 A,因此需要去编译它。为了解析它,我们也需要知道在哪里分配变量。就像我说的:你需要知道从内部函数引用了上面。所以我们完全解析了 B 函数。

现在我们假定预解析需要1费,解析需要2费。编译它需要另外的2费,但是我们实际上编译的是压缩的版本,因此可以忽略。 假如现在运行 A 函数,那么将花费 3*(f + A + B) + 2*(A + B)。如果 A 将会调用 B,我们就花费另外的2费用于 B 函数。

一方面,要得到一个内部函数,你需要解析一大堆。 另一方面,顶层函数越多,解析它的成本就越高,因为你要算上解析所有嵌套函数的时间。

建议的解决方案

那么计划怎么解决呢?

  1. 预解析的同时也进行范围解析(scope resolution),这样未编译部分的花费会从2降低到1.x。

  2. 将函数的上下文内存分配信息序列化到持久存储中,以避免不必要的重解析成本。

  3. 立即编译可能会支持 ! 和 , 。

至于成本?所有懒解析函数在初始加载时的开销为1.x,如果实际使用则为3.x。.x是内部函数范围解析和序列化的额外未知成本。

立即编译的优点是,对于已知的立即执行的顶级函数,我们可以进一步将成本从3.x下降到2。它是从顶层向内的。如果我们决定不将预解析(eagerly parse)作为主编译工作的一部分,那么我们可以等到它被执行,这样我们至少可以确定只需要支付实际使用的功能的编译成本(2解析和2编译)。

立即编译的缺点是我们需要在解析和编译之间在内存中保持AST(Abstract syntax tree)。显著增加了使用内存的峰值。如果我们可以预解析那些在被立即解析的函数的内部函数,情况可能会看起来好多了。即使如此,在低内存设备上,我们应该禁用启发式的立即编译。

如果我们序列化这些数据,那么在热启动时就完完全全不需要去查看未使用的代码。热启动时,即使在顶层的时候也是与启发式的立即编译不相关,因为我们将只解析/编译我们需要的函数。 搭载了比使用的代码还要多10倍以上的页面将会立即热启动。(目前已经可以是这种情况,但它是一个有点hit-and-miss)。

相关链接:

1.Abstract syntax tree

[翻译] V8引擎的解析的更多相关文章

  1. 深入V8引擎-引擎内部类管理解析

    v8的初始化三部曲,前面花了三篇解决了第一步,由于只是生成了一个对象,第二步就是将其嵌入v8中,先看一下三个步骤. // 生成默认Platform对象 std::unique_ptr<v8::P ...

  2. jQuery 2.0.3 源码分析Sizzle引擎 - 词法解析

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 浏览器从下载文档到显示页面的过程是个复杂的过程,这里包含了重绘和重排.各家浏览器引擎的工作原理略有差别,但也有一定规则. 简 ...

  3. 分析Sizzle引擎 - 词法解析

    分析Sizzle引擎 - 词法解析 声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 浏览器从下载文档到显示页面的过程是个复杂的过程,这里包含了重绘和重排.各家浏览器引擎的工 ...

  4. V8引擎嵌入指南

    如果已读过V8编程入门那你已经熟悉了如句柄(handle).作用域(scope)和上下文(context)之类的关键概念,以及如何将V8引擎作为一个独立的虚拟机来使用.本文将进一步讨论这些概念,并介绍 ...

  5. JavaScript工作机制:V8 引擎内部机制及如何编写优化代码的5个诀窍

    概述 JavaScript引擎是一个执行JavaScript代码的程序或解释器.JavaScript引擎可以被实现为标准解释器,或者实现为以某种形式将JavaScript编译为字节码的即时编译器. 下 ...

  6. JavaScript是如何工作的02:深入V8引擎&编写优化代码的5个技巧

    概述 JavaScript引擎是执行 JavaScript 代码的程序或解释器.JavaScript引擎可以实现为标准解释器,或者以某种形式将JavaScript编译为字节码的即时编译器. 以为实现J ...

  7. 深入浏览器工作原理和JS引擎(V8引擎为例)

    浏览器工作原理和JS引擎 1.浏览器工作原理 在浏览器中输入查找内容,浏览器是怎样将页面加载出来的?以及JavaScript代码在浏览器中是如何被执行的? 大概流程可观察以下图: 首先,用户在浏览器搜 ...

  8. 高性能JavaScript模板引擎原理解析

    随着 web 发展,前端应用变得越来越复杂,基于后端的 javascript(Node.js) 也开始崭露头角,此时 javascript 被寄予了更大的期望,与此同时 javascript MVC ...

  9. 精读《V8 引擎 Lazy Parsing》

    1. 引言 本周精读的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎为了优化性能,做了怎样的尝试吧! 这篇文章介绍的优化技术叫 preparser,是通过跳过不必要函数编译的方式优化性 ...

随机推荐

  1. C#多态“说来也说”——逻辑层BLL中的多态使用

    本文版权归博客园和作者吴双本人共同所有.欢迎转载,转载和爬虫请注明原文地址 http://www.cnblogs.com/tdws/p/5861842.html 昨天晚上,有个朋友说学了好久,依然没搞 ...

  2. Spring boot: Request method 'DELETE' not supported, Request method 'PUT' not supported, Request method 'POST' not supported

    GET,POST,PUT,DELETE, Spring都支持,不要怀疑Spring, 一定是前端发送的rest 请求和后端的响应不匹配, 查找原因以及解决办法, 很简单 用chrome打开F12控制台 ...

  3. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  4. java 开发模式

    Java-开发模式 Java Web开发方案有多种,这里列举一些经典的开发模式进行横向比较JSP+JAVABEAN开发模式:    特点:该模式将业务逻辑与页面表现进行分离,在一定程度上增加了程序的可 ...

  5. MVC跨项目路由

    我们在实际应用开发中,经常遇到多人共同开发维护同一个项目情况,所以不免会出现其中一个人代码出现bug质量问题导致整个项目就原地“爆炸”的惨状.在之前公司经常遇到某个人忘记更新(我就做个此事[" ...

  6. Js: Extensible Calendar Examples

    http://ext.ensible.comhttps://github.com/bmoeskau/Extensiblehttps://github.com/TeamupCom/extensibleh ...

  7. Atittit.研发公司的组织架构与部门架构总结

    Atittit.研发公司的组织架构与部门架构总结 1. archi组织架构与 部门规划2 1.1. 最高五大组织机构2 1.2. 宗教事务部2 1.3. 制度与重大会议委员会2 1.4. 纠纷处理部: ...

  8. java web 之客户关系管理系统

    这个周末真的是觉得自己学会了一个比较高大上的本领,为什么这么觉得呢?那是因为星期六的时候觉得自己可以看看源码能做出来,可是让我头疼的是花费了一上午的时间还是没有弄出来,还好上天给了我机会,要是没有老师 ...

  9. Android界面架构(Activity,PhoneWiondow,DecorView)简介

    在一个Android应用程序中,用户界面通过View和ViewGroup对象构建.所有View的子类成为"Widget",所有ViewGroup的子类成为"Layout& ...

  10. iOS NSNotificationCenter详解

    通知中心的特点: 1:同步执行 2: 一对多发送消息 3: 降低程序耦合度 通知中心是单例,目的就是从任意一个发送消息到任意一个接收者,是同步执行的. 那么什么是同步呢? 用网上经典的说法,就是我叫朋 ...