V8如何处理JS

简介: Chromium本身就是一个浏览器Chrome浏览器一般选择Chromium的稳定版本作为它的基础浏览器大战,其实就是渲染引擎之争v8是「JS虚拟机」的一种源代码对 V8 来说只是「一堆字符串」执行JS代码核心流程 1. 先编译 2. 后执行V8采用「JIT」(Just In Time)技术提升效率


人的本能就是对不太明白的东西敬而远之

一语中的

  1. Chromium本身就是一个浏览器
  2. Chrome浏览器一般选择Chromium的稳定版本作为它的基础
  3. 浏览器大战,其实就是渲染引擎之争
  4. v8是「JS虚拟机」的一种
  5. 源代码对 V8 来说只是「一堆字符串」
  6. 执行JS代码核心流程 1. 先编译 2. 后执行
  7. V8采用「JIT」(Just In Time)技术提升效率

文章概要

  • 浏览器简史:从群雄涿鹿到一家独大
  • V8:一款高性能JS和WebAssembly引擎
  • 执行JS代码的流程

在聊我们今天主角V8之前,我感觉有必要简单的把浏览器的发展史描述一下。「以史为镜,可以知兴替」

浏览器简史:从群雄涿鹿到一家独大

提到浏览器,Berners-Lee[1]是一个不得不提的人。Berners-Lee是W3C组织的理事,他在1990年发明了世界上第一个浏览器WorldWideWeb(后改名为Nexus)。

如果大家想试试第一款浏览器,那就体验一下哇[2] (自备🪜)

1993年,浏览器Mosaic[3]诞生,这就是后来的网景(Netscape)浏览器。在当时,网景浏览器大受欢迎,占据了绝大多数的市场份额。

受Mosaic浏览器的影响,微软于1995年推出了Internet Explorer(IE)浏览器,自此第一次浏览器大战正式打响。收益于Windows操作系统,IE逐渐取代了网景浏览器的领导地位。第一次浏览器大战以IE获胜收场。

处于低谷的网景公司于1998年成立了Mozilla基金会,在该基金会推动下,网景公司主导开发FireFox 浏览器。2004年发布1.0版本,拉开了第二次浏览器大战的序幕。

在FireFox浏览器发布1.0版本的前一年(2003年),苹果发布了Safari浏览器。并于2005年,苹果公司发起了一个新的开源项目 Webkit4(它是Safari浏览器的内核)。

2008年,Google公司以苹果开源项目Webkit作为内核,创建了一个新的项目 Chromium[5] (自备🪜)。在Chromium项目的基础上,Google发布了自己的浏览器Chrome。 「Chromium本身就是一个浏览器」,而不是Chrome浏览器内核,Chrome浏览器一般选择Chromium的稳定版本作为它的基础。Chromium是开源试验场。

自此,桌面浏览器形成了三足鼎立的局面 (IE/FireFox/Chrome)。

而随着时间的推移,Chrome浏览器在桌面领域一骑绝尘。将原来的对手抛到了脑后。根据statcounter[6]的最新统计,Chrome浏览器已经占据了半壁江山。

浏览器大战,其实就是渲染引擎之争

Chrome/Safari的渲染引擎,其实是一脉相承的。都是基于Webkit直接开发或者衍生出来的。

V8:一款高性能JS和WebAssembly引擎

用了一小段八股文描述了一下,浏览器的发展历史和现在浏览器的市场占有情况。发现Chrome以绝对的优势在浏览器市场称雄称霸。本着**「打不过,那就加入它」**的不抵抗方针,我们后面所有的文章,都用Chrome来讲解和实验。

时间不早了,我们干点正事哇。

V8是谷歌用C++编写的开源高性能JavaScriptWebAssembly引擎。它被用于Chrome和Node.js等。

(针对JS的介绍,可以参考之前写的JS篇之数据类型那些事儿[7],并且后期我们也会有针对该技术的介绍和分析。)

简单的说就是:

v8是**「JS虚拟机」**的一种

(除了V8,还有其他类型的JS虚拟机。

例如Safari中的JavaScriptCore,FireFox中的TraceMonkey等)

CPU是如何运行程序的文章中介绍,程序(高级语言)如果被CPU识别和执行,就需要进行**「转换」**。而这个转换操作又根据语言特性分为:1. 解释执行 2. 编译执行。 昨天我们通过对一段C代码,进行分析、执行,了解了编译执行的过程。而针对解释执行,却没有举例说明。今天,让我们把这个坑给填上。

把 V8 看成是一个虚构出来的计算机,也称为**「虚拟机」。虚拟机通过模拟实际计算机的各种功能来实现代码的执行。如模拟实际计算机的 CPU、堆栈、寄存器等, 并且还有属于它自己的一套「指令系统」**。

可以简单的把JS虚拟机理解成一个**「翻译」**程序: 将人类能够理解的编程语言 JS,翻译成机器能够理解的机器语言。


执行JS代码的流程

准备工作

需要准备执行 JS 时所需要的一些基础环境

  • 初始化了内存中的堆和栈结构
  • JS全局执行上下文 (包含了执行过程中的全局信息, 比如一些内置函数,全局变量等信息)
  • 全局作用域 (包含了一些全局变量, 在执行过程中的数据都需要存放在内存中)
  • 「初始化消息循环系统」 (1. 消息驱动器 2. 消息队列)

执行流程

  1. V8 接收到要执行的 JS 源代码 (源代码对 V8 来说只是**「一堆字符串」**,V8 并不能直接理解这段字符串的含义)
  2. V8结构化这段字符串,生成了**「抽象语法树」** (AST),同时还会生成相关的**「作用域」**
  3. 生成字节码(介于 AST 和机器代码的中间代码)。与特定类型的机器代码无关
  4. 解释器(ignition),按照顺序解释执行字节码,并输出执行结果。

从图中得出一个结论:

执行JS代码核心流程 1. 先编译 2. 后执行

通过V8将js转换为字节码然后经过解释器执行输出结果的方式执行JS,有一个弊端就是,如果在浏览器中再次打开相同的页面,当页面中的 JavaScript 文件没有被修改,再次编译之后的二进制代码也会保持不变,意味着编译这一步**「浪费了 CPU 资源」**。

为了,更好的利用CPU资源,V8采用**「JIT」**(Just In Time)技术提升效率:而是混合编译执行和解释执行这两种手段。

1.解释执行的启动速度快,但是执行时的速度慢

2.编译执行的启动速度慢,但是执行时的速度快

为了能够实现编译执行,V8又引入了TurboFan(优化编译器),并且在解释执行字节码的过程中,如果发现了某一段代码会被**「重复多次执行」**,监控机器人就会将这段代码标记为热点代码

当某段代码被标记为热点代码后,V8 就会将这段字节码丢给优化编译器(TurboFan),优化编译器会在后台将字节码编译为**「二进制代码」**,然后再对编译后的二进制代码执行优化操作,优化后的二进制机器代码的执行效率会得到大幅提升。

同时,由于JS是动态语言, 对象的结构和属性是可以在运行时任意修改的,经过优化编译器优化过的代码只能针对某种固定的结构。一旦在执行过程中,对象的结构被动态修改了, 优化之后的代码势必会变成无效的代码,优化编译器就需要执行**「反优化操作」**,经过反优化的代码,下次执行时就会回退到解释器解释执行。


参考资料:

  1. Webkit技术内幕
  2. Google V8

Reference

[1]

Berners-Lee: baike.baidu.com/item/%E8%92…

[2]

体验一下哇: worldwideweb.cern.ch/browser/#ht…

[3]

Mosaic: baike.baidu.com/item/Mosaic…

[4]

Webkit: webkit.org/

[5]

Chromium: www.chromium.org/

[6]

statcounter: gsa.statcounter.com/browser-mar…

[7]

JS篇之数据类型那些事儿: mp.weixin.qq.com/s/v-nqPc22f…


相关文章
|
Web App开发 缓存 移动开发
V8 JS AOT化的探索与实践
JS 语言的动态性非常优秀,其弱类型等语言特性也使得一线业务开发者更容易上手,但这也导致 JS 每一次运行前都要重复编译,使得 JS 的执行性能不理想;虽然之前 UC 内核有做过 Code Cache 方案,但支持的场景不够完整,与原生 Native 的技术方案比,尤其是首次启动场景(如各类大促活动等)还是有比较大的差距。为了能尽可能做到与 Native 对标,缩小性能差距,同时让业务开发者无感,我们开发了 JS AOT 功能。本分享将结合目前集团内自有业务形态,以及 JS 在 Web 中的执行过程,介绍JS AOT是如何设计和实现的,以及能给业务带来哪些收益。本篇分享来自阿里巴巴的喻世江在第
2175 0
V8 JS AOT化的探索与实践
|
存储 JavaScript 前端开发
从 V8 优化看高效 JavaScript
从 V8 优化看高效 JavaScript
96 0
|
6月前
|
Web App开发 前端开发 JavaScript
探索 V8 引擎的内部:深入理解 JavaScript 执行的本质
探索 V8 引擎的内部:深入理解 JavaScript 执行的本质
探索 V8 引擎的内部:深入理解 JavaScript 执行的本质
|
自然语言处理 JavaScript 前端开发
V8 是如何执行 JavaScript 代码的
V8 是如何执行 JavaScript 代码的
114 0
|
存储 Web App开发 监控
Js中的垃圾回收及V8引擎的优化
Js中的垃圾回收及V8引擎的优化
291 0
|
Web App开发 Rust JavaScript
V8 JavaScript引擎
V8 JavaScript引擎
|
XML 存储 缓存
揭开使用 V8 作为目标引擎🔬的 JavaScript 代码处理的神秘面纱
揭开使用 V8 作为目标引擎🔬的 JavaScript 代码处理的神秘面纱
147 0
|
消息中间件 存储 自然语言处理
图解 Google V8 # 09:运行时环境:运行JavaScript代码的基石
图解 Google V8 # 09:运行时环境:运行JavaScript代码的基石
284 0
图解 Google V8 # 09:运行时环境:运行JavaScript代码的基石
|
存储 JavaScript 前端开发
图解 Google V8 # 02:函数即对象:一篇文章彻底搞懂 JavaScript 的函数特点
图解 Google V8 # 02:函数即对象:一篇文章彻底搞懂 JavaScript 的函数特点
150 0
图解 Google V8 # 02:函数即对象:一篇文章彻底搞懂 JavaScript 的函数特点
|
Web App开发 JavaScript 前端开发
图解 Google V8 # 01:V8 是如何执行一段 JavaScript 代码的?
图解 Google V8 # 01:V8 是如何执行一段 JavaScript 代码的?
209 0
图解 Google V8 # 01:V8 是如何执行一段 JavaScript 代码的?
下一篇
无影云桌面