JavaScript为什么快--第三篇

简介: 原视频上一篇文章JavaScript 为什么快--第二篇讲到,抽象语法树(Abstract Syntax Tree,AST)生成字节码。本篇文章将延续字节码后的,JavaScript代码是如何执行的。

原视频

上一篇文章JavaScript 为什么快--第二篇讲到,抽象语法树(Abstract Syntax Tree,AST)生成字节码。本篇文章将延续字节码后的,JavaScript代码是如何执行的。
How JavaScript Engines Work by Franziska Hinkelmann @ Web Rebels 2017
JS引擎渲染逻辑图_jpeg

结论先行

我们以前看到的优化建议,对V8而言,很可惜这些经验逐渐都没用了。
Avoid keywords(eval, try-catch, ...) not useful anymore.

经验之谈的优化点,对于日益精进的V8来说并不可靠,最可靠的优化是”静态类型“
Write code that looks "statically typed"

JavaScript引擎使用runtime时采集的类型信息,优化提速。所以虽然JavaScript虽然是动态类型的语言,但我们要尽可能的写静态类型的代码。

另外目前和热门的WebAssembly也使用TurboFan优化代码。

JavaScript引擎有哪些?

  • 浏览器:V8, Chakra, JavaScriptCore, SpiderMonkey
  • Node.js:V8, Chakra, SpiderNode
  • Electron: V8
  • IoT: Duktape, JerryScript

JavaScript背景

JavaScript实现EcmaScript标准,由TC39制定。正是这个标准,导致JavaScript无论是哪个JS引擎实现,都需要考虑一堆的类型判断。例如类型转化的定义:https://www.ecma-international.org/ecma-262/9.0/index.html#sec-type-conversion

JavaScript一个很吸引人的特性就是:动态类型语言(var定义变量),C++是静态类型语言。而JS引擎也是C++实现的,所以对于引擎开发者来说还是需要考虑将JS的变量转换为静态类型。

为了快速解析并运行JavaScript脚本,V8引入了JIT,快速解析出字节码,由基线编译器生成"粗糙"的机器码去执行,这样实现了快速执行。
但是后果就是这些基线代码效率很低,因为Ecma的标准中有大量的歧义和类型判定。
所以V8又引入了优化编译器,将经常执行的”hot“函数优化机器码提升,这些函数的执行效率。

注释:Just In Time(JIT) Compilation
Generate machine code during runtime, not ahead of time(AOT)

JS引擎渲染单元逻辑

JS引擎渲染单元名称

基线编译器

将字节码转化成基线机器码,去执行。并且将经常执行的”hot“函数,发给优化编译器,生成优化后的函数机器码提效。

优化编译器

re-compoile, 使用之前执行的类型信息优化,重新编译”hot“函数。(所以不要改变类型!!!)
de-compile, 一旦类型改变,就会失效,就会跌回baseline,重新优化。

优化点:永远构造相同类型的对象:

//举个栗子
function load(obj) {
    return obj.x;
}
load({x:4, a: 1});
load({x:4, a: 2});
load({x:4, a: 3});
load({x:4, b: 1});//这里会触发de-compile
//我们应该这样使用:
load({x: 4, a: 7, b: undefined, c: undefined});
load({x: 4, a: undefined, b: 1, c: undefined});
load({x: 4, a: undefined, b: undefined, c: 3});

JS引擎渲染DeCompile逻辑

//举个栗子
function add(obj) {
  return 1+obj.x;//JavaScript 中"+"号的复杂定义;obj.x的Property lookup
}
add({x:7});//+ operator according to spec(slow)
add({x:42});
...
add({x:123});//"hot",they "always integers",fast code for integer addition(fast);
add({x:'Hello;}); //"hot" failed, + operator according to spec(slow)

V8中的类型比较:HaveSameMap

Shape of object = map = hidden class

var obj1 = {x:5};
var obj2 = {x:17};
console.log(%HaveSameMap(obj1, obj2));

可以用V8参数开启这个内置C函数来检查2个Object是否一致:$ node --allow-natives-syntax maps.js

目录
相关文章
|
Web App开发 JavaScript 前端开发
JavaScript为什么快--第一篇?
V8让JavaScript更快的秘密;V8的JavaScript执行管道;TurboFan&Ignition
2778 0
|
4天前
|
存储 JavaScript 前端开发
从零开始学习Vue.js
Vue.js 是一种流行的前端框架,它使用简单,灵活且易于上手。如果你是一个前端开发者,并想要学习 Vue.js,本文将为您提供一个从零开始的指南。我们将探讨 Vue.js 的基础知识和常用功能,以及如何构建一个简单的 Vue.js 应用程序。
|
6天前
|
缓存 JavaScript 前端开发
JavaScript:get和post的区别,2024年最新3-6岁儿童学习与发展指南心得体会
JavaScript:get和post的区别,2024年最新3-6岁儿童学习与发展指南心得体会
|
7天前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
8天前
|
XML Web App开发 前端开发
字节FE:JavaScript学习路线图
字节FE:JavaScript学习路线图
36 0
|
8天前
|
存储 移动开发 JavaScript
学习javascript,前端知识精讲,助力你轻松掌握
学习javascript,前端知识精讲,助力你轻松掌握
|
8天前
|
JavaScript 前端开发 测试技术
学习JavaScript
【4月更文挑战第23天】学习JavaScript
15 1
|
8天前
|
JavaScript 前端开发 应用服务中间件
node.js之第一天学习
node.js之第一天学习
|
8天前
|
运维 JavaScript 前端开发
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
|
8天前
|
JavaScript
Vue.js学习详细课程系列--共32节(6 / 6)
Vue.js学习详细课程系列--共32节(6 / 6)
29 0