[翻译] V8引擎的解析
本文档介绍了 V8 引擎是如何解析 JavaScript 源代码的,以及我们将改进它的计划。
动机
我们有个解析器和一个更快的预解析器(~2x),但是预解析器对大多数现代 JavaScript 无用。此外假如还没有编译了外部函数,否则我们必须再解析一遍内部函数。 那现在的 V8 引擎什么时候会立即编译(eager compilation)呢?
顶层的括号函数(function...
在 ( 之后的不是函数声明的内部函数
当我们把一个内部函数当做非脚本级的一部分来解析的时候,是不能使用预解析器的。我们将不会编译一个内部函数,所以如果我们永远不先行编译函数,那么一般的 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 函数。
一方面,要得到一个内部函数,你需要解析一大堆。 另一方面,顶层函数越多,解析它的成本就越高,因为你要算上解析所有嵌套函数的时间。
建议的解决方案
那么计划怎么解决呢?
预解析的同时也进行范围解析(scope resolution),这样未编译部分的花费会从2降低到1.x。
将函数的上下文内存分配信息序列化到持久存储中,以避免不必要的重解析成本。
立即编译可能会支持 ! 和 , 。
至于成本?所有懒解析函数在初始加载时的开销为1.x,如果实际使用则为3.x。.x是内部函数范围解析和序列化的额外未知成本。
立即编译的优点是,对于已知的立即执行的顶级函数,我们可以进一步将成本从3.x下降到2。它是从顶层向内的。如果我们决定不将预解析(eagerly parse)作为主编译工作的一部分,那么我们可以等到它被执行,这样我们至少可以确定只需要支付实际使用的功能的编译成本(2解析和2编译)。
立即编译的缺点是我们需要在解析和编译之间在内存中保持AST(Abstract syntax tree)。显著增加了使用内存的峰值。如果我们可以预解析那些在被立即解析的函数的内部函数,情况可能会看起来好多了。即使如此,在低内存设备上,我们应该禁用启发式的立即编译。
如果我们序列化这些数据,那么在热启动时就完完全全不需要去查看未使用的代码。热启动时,即使在顶层的时候也是与启发式的立即编译不相关,因为我们将只解析/编译我们需要的函数。 搭载了比使用的代码还要多10倍以上的页面将会立即热启动。(目前已经可以是这种情况,但它是一个有点hit-and-miss)。
相关链接:
[翻译] V8引擎的解析的更多相关文章
- 深入V8引擎-引擎内部类管理解析
v8的初始化三部曲,前面花了三篇解决了第一步,由于只是生成了一个对象,第二步就是将其嵌入v8中,先看一下三个步骤. // 生成默认Platform对象 std::unique_ptr<v8::P ...
- jQuery 2.0.3 源码分析Sizzle引擎 - 词法解析
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 浏览器从下载文档到显示页面的过程是个复杂的过程,这里包含了重绘和重排.各家浏览器引擎的工作原理略有差别,但也有一定规则. 简 ...
- 分析Sizzle引擎 - 词法解析
分析Sizzle引擎 - 词法解析 声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 浏览器从下载文档到显示页面的过程是个复杂的过程,这里包含了重绘和重排.各家浏览器引擎的工 ...
- V8引擎嵌入指南
如果已读过V8编程入门那你已经熟悉了如句柄(handle).作用域(scope)和上下文(context)之类的关键概念,以及如何将V8引擎作为一个独立的虚拟机来使用.本文将进一步讨论这些概念,并介绍 ...
- JavaScript工作机制:V8 引擎内部机制及如何编写优化代码的5个诀窍
概述 JavaScript引擎是一个执行JavaScript代码的程序或解释器.JavaScript引擎可以被实现为标准解释器,或者实现为以某种形式将JavaScript编译为字节码的即时编译器. 下 ...
- JavaScript是如何工作的02:深入V8引擎&编写优化代码的5个技巧
概述 JavaScript引擎是执行 JavaScript 代码的程序或解释器.JavaScript引擎可以实现为标准解释器,或者以某种形式将JavaScript编译为字节码的即时编译器. 以为实现J ...
- 深入浏览器工作原理和JS引擎(V8引擎为例)
浏览器工作原理和JS引擎 1.浏览器工作原理 在浏览器中输入查找内容,浏览器是怎样将页面加载出来的?以及JavaScript代码在浏览器中是如何被执行的? 大概流程可观察以下图: 首先,用户在浏览器搜 ...
- 高性能JavaScript模板引擎原理解析
随着 web 发展,前端应用变得越来越复杂,基于后端的 javascript(Node.js) 也开始崭露头角,此时 javascript 被寄予了更大的期望,与此同时 javascript MVC ...
- 精读《V8 引擎 Lazy Parsing》
1. 引言 本周精读的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎为了优化性能,做了怎样的尝试吧! 这篇文章介绍的优化技术叫 preparser,是通过跳过不必要函数编译的方式优化性 ...
随机推荐
- wpf 列表、菜单 收起与展开,通过Grid DoubleAnimation或者Expander实现
菜单收缩有很多种方法具体如何实现还是看个人想法: 第一种通过后台控制收起与展开: 效果图: 代码 : <Grid> <Grid.ColumnDefinitions> <C ...
- Monkey Patch/Monkey Testing/Duck Typing/Duck Test
Monkey Patch Monkey Testing Duck Typing Duck Test
- CodeMirror简介
Javascript由于其作为Web标准的独特地位,很多人甚至希望它能一统前后端开发. Javascript的本质工作首先肯定的Web前端开发,本文主要想介绍的CodeMirror是一款Web Edi ...
- PHP中模拟JSONArray
前面整理过一篇文章,描述php中的array与json的array和object的转换关系.http://www.cnblogs.com/x3d/p/php-json-array-object-typ ...
- django入门之模板的用法
1.为什么要使用模板? 看下以前的代码 #-*- coding:utf-8 -*- from django.shortcuts import render from django.http impor ...
- Delphi_01_控制台版HelloWorld
对于Windows下的控制台编程,我相信很多人都不陌生.而C语言开始的著名的“Hello world”程序基本是学习编程的第一步.我想对于 RAD开发,大家熟悉的一般都是GUI编程,而对于consol ...
- 5.1 JS中Object类型
1.Object类型是引用类型中的一种. 2.创建Object实例(对象)的方式: 方式1:使用new操作符,后面跟上Object构造函数.如: var obj = new Object();//创建 ...
- Dynamic CRM 查询实体记录 被共享给了 哪个用户
--客户表名"new_customer" SELECT u.FullName AS 被共享人,a.new_name AS 客户名称,sup.SystemUserid AS 共享人I ...
- SQL Server快速查询某张表的当前行数
传统做法可能是select count(1) 但是往往会比较慢.推荐如下做法: ) CurrentRowCount FROM sys.sysindexes WHERE id = OBJECT_ID(' ...
- zabbix完整安装
一.nginx安装 1.必要软件准备: 为了支持rewrite功能,我们需要安装pcre: yum install pcre-* 需要ssl的支持,如果不需要ssl支持,请跳过这一步: yum ins ...