前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >V8如何处理JS

V8如何处理JS

作者头像
前端柒八九
发布2022-08-25 14:11:22
8470
发布2022-08-25 14:11:22
举报
文章被收录于专栏:柒八九技术收纳盒

一语中的

  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年,苹果公司发起了一个新的开源项目 Webkit[4](自备🪜)(它是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: https://baike.baidu.com/item/%E8%92%82%E5%A7%86%C2%B7%E4%BC%AF%E7%BA%B3%E6%96%AF%C2%B7%E6%9D%8E/8868412?fr=aladdin

[2]

体验一下哇: https://worldwideweb.cern.ch/browser/#https://worldwideweb.cern.ch/browser/default.html

[3]

Mosaic: https://baike.baidu.com/item/Mosaic%E6%B5%8F%E8%A7%88%E5%99%A8/9963015?fr=aladdin

[4]

Webkit: https://webkit.org/

[5]

Chromium: www.chromium.org/

[6]

statcounter: http://gsa.statcounter.com/browser-market-share/desktop/worldwide

[7]

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端柒八九 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一语中的
  • 文章概要
  • 浏览器简史:从群雄涿鹿到一家独大
  • V8:一款高性能JS和WebAssembly引擎
  • 执行JS代码的流程
    • 准备工作
      • 执行流程
        • Reference
    相关产品与服务
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档