c++re是为什么_JavaScript为什么快--第三篇

本文探讨了JavaScript引擎如V8如何利用类型信息进行优化,包括基线编译器和优化编译器的工作原理,强调了静态类型编码的重要性。同时提到了WebAssembly作为另一种优化代码的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原视频

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

2dce5ff46db56282f463b7473f28d4ec.png
JS引擎执行流

结论先行

我们以前看到的优化建议,对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) CompilationGenerate machine code during runtime, not ahead of time(AOT)

a01f348e3796e0ef79fd2dcec4934601.png
JS引擎流模块

833a64213cae260319ad05d567509162.png
JS引擎流V8模块名称

基线编译器

将字节码转化成基线机器码,去执行。并且将经常执行的”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});

2a30dc304954219f2703307bc05bf461.png
De-Compile例子

Javascript//举个栗子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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值