开发者社区> 秦粤> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
JavaScript为什么快--第一篇?
V8让JavaScript更快的秘密;V8的JavaScript执行管道;TurboFan&Ignition
1613 0
利用JavaScript实现二级联动
利用JavaScript实现二级联动 要实现JavaScript二级联动效果,首先要确定需要哪些技术: 二维数组 for in循环 new Option(text,value,true,true) add(option,null) onchange() 表单事件 HTML代码: <!-- <input type="text" id="text"> --> 请选择省份: <select name="" id="provinces"> <!-- <option value="江苏省">江苏省</option>
0 0
JavaScript函数柯里化的实现原理,进来教你完成一个自己的自动实现柯里化方法
JavaScript函数柯里化的实现原理,进来教你完成一个自己的自动实现柯里化方法
0 0
weex-自定义module,实现weex在iOS的本地化,js之间互相跳转,交互,传值(iOS接入weex的最佳方式)
weex-自定义module,实现weex在iOS的本地化,js之间互相跳转,交互,传值(iOS接入weex的最佳方式)
0 0
JS中实现或退出全屏
JS中实现或退出全屏
0 0
前端:JS实现双击table单元格变为可编辑状态
前端:JS实现双击table单元格变为可编辑状态
0 0
【前端算法】JS实现数字千分位格式化
JS实现数字千分位格式化的几种思路,以及它们之间的性能比较
0 0
【前端算法】用JS实现快速排序
理解数组方法里面运用到的算法,splice 和 slice的区别
0 0
【前端算法】javaScript实现二分查找
如何使用JS实现一个合格的二分查找
0 0
+关注
秦粤
Ex百度Phper,Now阿里Noder
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Javascript中的函数
立即下载
Javascript异步编程
立即下载
JS零基础入门教程(上册)
立即下载