JS引擎(1):JS引擎擂台赛,JavaScript引擎的特征比较及术语科普
上篇介绍过JavaScript引擎的历史,《JS引擎(0):起底各种JavaScript引擎群雄争霸之路》
一些流行的 JavaScript 引擎
SpiderMonkey ,Brendan Eich 在Netscape创建,由 C/C++ 语言开发,可适配 ECMA-262 Edition 5 及其之后的标准版本
Rhino,由 Norris Boyd(归属Netscape)创建,则是一个 Java 语言开发的 JavaScript 实现,跟SpiderMonkey
Google 的 V8,在 Google Chrome 浏览器和较新的 Opera 浏览器中使用。这同时也是Node.js使用的引擎。
JavaScriptCore (SquirrelFish/Nitro),被用在了一些 WebKit 浏览器如 Apple Safari。
Carakan,用在旧版本 Opera 中。
The Chakra 引擎
几种较老的JavaScript引擎的特征:
不懂的术语,可以跳转至 JavaScript引擎相关关术语解析
| SpiderMonkey | JScript | KJS | |
| 实现语言 | C | C++ | C++ |
| 执行模式 | 解释执行 | 解释执行 | 解释执行 |
| 解释器 | 字节码解释器:基于栈的字节码 | 字节码解释器:基于栈的字节码 | 树遍历解释器 |
| 动态编译器 | 无 | 无 | 无 |
| 自动内存管理 | mark-and-sweep | mark-and-sweep | mark-and-sweep |
| 对象布局 | ? | 基本上是HashTable | ? |
| 针对密集数组的优化 | ? | 无 (JScript < 5.7);有(JScript 5.8) | ? |
| Inline-cache | ? | ? | ? |
| 值表现形式 | tagged-value | 堆对象 | 堆对象 |
| Function.prototype.toString() | 从字节码反编译 | ? | ? |
在Google推出V8之后,业界受到巨大冲击。V8的性能远高于当时所有其它JavaScript引擎,可以有效支撑起当时兴起的大量使用JavaScript的Web应用。
各大JavaScript引擎的实现者都坐不住了,像打了鸡血似的使劲优化优化再优化。先是把已在其它HLLVM上得到充分验证的优化技术引入到JavaScript引擎中,然后再针对JavaScript语言的特点做专项优化。
现在(2013-04)几种主流的JavaScript引擎的特征:
| V8 | SpiderMonkey | Chakra | Nitro | Nashorn | |
| 实现语言 | C++/汇编 | C++ | C++ | C++/汇编 | Java |
| 执行模式 | 纯编译: 两层编译 | 解释/编译混合式: 3层执行模式 | 解释/编译混合: 2层执行模式,后台编译 | 解释/编译混合: 3层执行模式 | 纯编译 |
| 解释器 | 无 | 字节码解释器 | 字节码解释器:基于寄存器的字节码 | 字节码解释器 LLInt:基于寄存器的字节码 | 无 |
| 动态编译器 | 初级编译器 + 优化编译器 | 初级编译器 Baseline + 优化编译器 IonMonkey | 有 | 初级编译器 method JIT + 优化编译器 DFG JIT | 有 |
| 自动内存管理 |
分代式GC: 初生代: copying收集器; 年老代: 增量式mark-and-sweep, 可选compact |
分代式GC |
分代式GC: 初生代: copying收集; 年老代: 并发式mark-and-sweep |
分代式GC | 依赖于底层JVM的GC |
| 对象布局 | 紧凑+隐藏类 Map | 紧凑+隐藏类 Shape | 紧凑+隐藏类 | 紧凑+隐藏类 Structure | 紧凑+隐藏类 PropertyMap |
| 针对密集数组的优化 | 有 | 有 | 有 | 有 | 有 |
| Inline-cache | MIC/PIC | PIC | PIC | PIC | MIC/PIC |
| 值表现形式 | tagged-pointer / IEEE 754 double / integer | pun-boxing | tagged-value | NaN-boxing | 堆对象 / integer |
| 正则表达式 | 编译 Irregexp | 编译 | 编译 | 编译 WREC | 混合 |
| Function. prototype. toString() | 保留源码原文 | (2012年7月前) 从字节码反编译; (761723后) 保留源码原文 | ? | ? | 保留源码原文 |
JavaScript引擎相关术语解析
树遍历解释器:tree-walking interpreter。遍历抽象语法树来解释执行的解释器。
对象布局: object representation 或者 object layout。指在堆上分配的JavaScript对象的在内存中的布局。
值表现形式: value representation。注意跟“对象布局”说的不是一件事。这个指的是原始类型数据、指向堆上分配的对象的指针之类的值的表现形式。对某些JavaScript引擎来说这是指“JSValue”背后在内存中的表现形式。新生代中的对象98%是“朝生夕死”的,所以并不需要按照1:1的比例来划分内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次性的复制到另外一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次性的复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8:1,也就是每次新生代中可用内存为整个新生代容量的90%(80%+10%),只有10%的内存会被“浪费”。
copying GC: 也叫scavenger。垃圾收集算法——复制算法,他将可用内存按容量划分为大小相等的两块,每次只使用其中一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。
现在的商业虚拟机都采用这种收集算法来回收新生代,这种算法的代价是将内存缩小为了原来的一半
IC,Inline caching,内联缓存。实际上是一门近30年的非常古老的技术,最初用在Smalltalk虚拟机上。工作原理:创建一个高速路来绕过运行时系统来读取对象的属性:对传入的对象及其属性作出某种假设,然后通过一个低成本的方式验证这个假设是否正确,如果正确就读取上次缓存的结果。在充满了动态类型和晚绑定以及其他古怪行为——比如eval——的语言里对一个对象作出合理的假设是非常困难的,所以我们退而求其次,让我们的读/写操作能够有学习能力:一旦它们看见某个对象它们就可以以某种方式来自适应,使得之后的读取操作在遇到类似结构的对象时能够更快地进行。在某种意义上,我们将要在读/写操作上缓存关于之前见过的对象的布局的相关知识——这也是内联缓存这个名字的由来。内联缓存可以被用在几乎所有需要动态行为的操作上,只要你可以找到正确的高速路:算数操作、调用自由函数、方法调用等等。有些内联缓存还能缓存不止一条快速通道,这些内联缓存就变成了多态的。
MIC: monomorphic inline-cache,单态内联缓存。有一个简单的直接类型检查开销,然后是普通的直接调用开销。
PIC: polymorphic inline-cache,多态内联缓存。
pun-boxing: Packed NaN unboxing,SpiderMonkey和LuaJIT似乎都在用pun boxing
当代JavaScript引擎之间有许多共通的实现技巧
当代JavaScript引擎之间有许多共通的实现技巧。多数优化会对JavaScript程序的行为做一定猜测(speculate),并基于猜测做激进优化(speculative optimization)。下面挑几个简单介绍一下。
从源语言到中间表示的编译器(source-to-IR compiler)
也叫做编译器的“前端”。
递归下降式语法分析器(recursive-descent parser)
运算符优先级式语法分析器(operator precedence parser)
deferred parser / diet parser(延迟语法分析)
从中间表示到目标代码的编译器(IR-to-target-code compiler)
也叫做编译器的“后端”。但因为这部分编译器经常被叫做“JIT”编译器,所以单独拿出来写
JIT style compiler: “just-in-time编译”狭义的定义是“即时编译”,也就是在某段代码即将第一次被执行时才对其编译。太早或太迟都不符合这个狭义版定义。所谓“JIT风格的编译器”通常意味着“编译是同步进行的”。这就自然的引出几个特征:
编译速度必须很快;
编译只能做有限的优化,只能选效费比高的来做。
optimizing compiler
多层编译(tiered compilation)
后台编译(background compilation)
类型反馈(type feedback)
类型特化(type specialization)
SSA-form IR
自动内存管理
分代式GC(generational GC)
增量式GC(incremental GC)
并发式GC(concurrent GC)
准确式GC(exact / accurate / type exact / type accurate / precise GC)
对象布局
紧凑对象布局 + 隐藏类
值表现形式
tagger-pointer 或 tagged-value
NaN-boxing
运行时系统
inline-cache
on-stack replacement
deoptimization
用native stack实现VM stack
cons-string 或者叫 rope 来优化字符串拼接
dependent string/sliced string 来优化字符串的子串操作
sparse array
B-tree
上面介绍的JavaScript引擎实现技巧也影响了“如何写出更高效的JavaScript代码”:尽量让代码的行为符合JavaScript引擎的猜测,效率就会高。
写类型稳定的代码
在构造器函数里声明和初始化所有属性
尽量不要delete属性;不要通过delete属性来把某个属性重置,赋值为undefined都好
不要把数组当一般对象用;不要把一般对象当数组用
参考内容:
各JavaScript引擎的简介,及相关资料/博客收集帖 https://hllvm-group.iteye.com/group/topic/37596
转载本站文章《JS引擎(1):JS引擎擂台赛,JavaScript引擎的特征比较及术语科普》,
请注明出处:https://www.zhoulujun.cn/html/webfront/browser/webkit/2020_0718_8522.html
JS引擎(1):JS引擎擂台赛,JavaScript引擎的特征比较及术语科普的更多相关文章
- js:我们应该如何去了解JavaScript引擎的工作原理(转)
http://www.nowamagic.net/librarys/veda/detail/1579 昨天收到一封来自深圳的一位前端童鞋的邮件,邮件内容如下(很抱歉,未经过他的允许,公开邮件内容,不过 ...
- 理解WebKit和Chromium: JavaScript引擎简介
转载请注明原文地址:http://blog.csdn.net/milado_nju 1. 什么是JavaScript引擎 什么是JavaScript引擎?简单来讲,就是能够提供执行JavaScript ...
- 【转】理解WebKit和Chromium: JavaScript引擎简介
转载请注明原文地址:http://blog.csdn.net/milado_nju1. 什么是JavaScript引擎什么是JavaScript引擎?简单来讲,就是能够提供执行JavaScript代码 ...
- 简介浏览器内核与JavaScript引擎
本文介绍了常用浏览器内核与JavaScript引擎 一.浏览器内核 Rending Engine, 顾名思义,称之为渲染网页内容的,将网页的代码转换为你看得见的页面,因为是排版,所以排版,所以肯定会有 ...
- 关于浏览器内核与javascript引擎的一些小知识
浏览器是我们每天几乎都必须使用的软件产品,可是对于自己每天都接触的浏览器,很多同学其实对其一无所知.今天异次元就跟大家说说关于浏览器内核的一些事儿吧,好让你了解多一点稍微内在的东西. 在下面的文章中主 ...
- 对JavaScript 引擎基础:Shapes 和 Inline Caches
全文有5个部分组成 1.JavaScript 引擎工作流程:介绍 JavaScript 引擎的处理流水线,这一部分会涉及到解释器/编译器的内容,且会分点介绍不同引擎间的差别与共同点: 2.JavaSc ...
- JavaScript 引擎基础:Shapes 和 Inline Caches
JavaScript 引擎基础:Shapes 和 Inline Caches hijiangtao 中国科学院大学 计算机应用技术硕士 260 人赞同了该文章 前言:本文也可以被称做 “JavaS ...
- JavaScript 引擎「V8」发布 8.0 版本,内存占用量大幅下降
上周,JavaScript 引擎「V8」的开发团队在该项目官方网站上正式宣布推出最新的 8.0 版本.这次更新的重点主要集中在错误修复及性能改善上,正式的版本将在数周后随着谷歌 Chrome 80 稳 ...
- JavaScript模板引擎artTemplate.js——如何引入模板引擎?
artTeamplate.js在github上的地址:artTemplate性能卓越的js模板引擎 引入模板引擎,就是引入外部javascript啦,并且artTemplate.js不依赖其他第三方库 ...
- Javascript模板引擎mustache.js详解
mustache.js是一个简单强大的Javascript模板引擎,使用它可以简化在js代码中的html编写,压缩后只有9KB,非常值得在项目中使用.本文总结它的使用方法和一些使用心得,内容不算很高深 ...
随机推荐
- HTML-8
(一)引用数据类型 object function array object JavaScript对象用花括号来书写 对象属性是name:value由逗号分隔 var x={firstname:&qu ...
- 阿里云上的rds 的隔离级别read committed 而不是repeatable-read设置原因
阿里云上的rds 的隔离级别 是read committed ,而不是原生mysql的"可重复读(repeatable-read)",他们是基于什么原因这样设置的? show va ...
- [Python急救站]草莓熊的绘制
草莓熊也是一个热门的图案,今天就用Python绘制一下 import turtle as t # 设置背景颜色,窗口位置以及大小 t.colormode(255) # 颜色模式 t.speed(0) ...
- Navicat 基于 GaussDB 主备版的快速入门
本文分享自华为云社区<Navicat 基于 GaussDB 主备版的快速入门>,作者:Navicat_China. Navicat Premium(16.2.8 Windows版或以上) ...
- Python+Yolov8+ONNX实时缺陷目标检测
相比于上一篇Windows10+Python+Yolov8+ONNX图片缺陷识别,并在原图中标记缺陷,有onnx模型则无需配置,无需训练. 优化了程序逻辑,降低了程序运行时间,增加了实时检测功能 目录 ...
- QT实战 之翻金币游戏
QT实战 之翻金币游戏 相较于原版的优化: 关卡数据不是用静态的config配置,而是动态生成,每次打开的关卡都生成不同的游戏数据,增加了可玩性: 关卡数据依据关卡等级的不同而生成不同难度的数据,随关 ...
- Modbus转PROFINET网关助力电子天平与西门子PLC无缝对接
背景: 在制药.食品科学和其他行业中,电子天平被广泛用于质量控制和分析实验.它们可以用于检测样品的净重.含量和浓度,并用于监测产品的制造过程. 常州某反应器公司实验室近期采购一批电子天平,现需要把电子 ...
- 学会XPath,轻松抓取网页数据
一.定义 XPath(XML Path Language)是一种用于在 XML 文档中定位和选择节点的语言.XPath的选择功能非常强大,可以通过简单的路径选择语法,选取文档中的任意节点或节点集.学会 ...
- Aiganize微信小程序开发手册二代
根据此表格, 现有三个模块: 活动模块 聊天模块 影子模块 现活动模块交与:赵坤亮.郝文章做 现聊天模块与用户信息交与:葛方杰.陈金鹏做影子模块待定,现做完那两块,已经有不错的用户体验了.
- 记一次解决RestTemplate和HttpClient请求结果乱码的问题
调用一个接口,发送POST请求,浏览器和Postman均返回正常,代码中用RestTemplate和HttpClient均返回乱码 开始一直以为是编码问题导致,网上查了解决方法,也看了源码,都不对症 ...