使用 D8 分析 javascript 如何被 V8 引擎优化的
在上一篇文章中我们讲了如何使用 GN 编译 V8 源码,文章最后编译完成的可执行文件并不是 V8,而是 D8。这篇我们讲一下如何使用 D8 调试 javascript 代码。
如果没有 d8,可以使用 node 代替。
新建文件 add-of-ints.js,输入以下内容:
function add(obj) {
return obj.prop + obj.prop;
}
const length = 1000 * 1000;
const o = { prop: 1 };
for (let i = 0; i < length; i++) {
add(o);
}
运行:
d8 --trace-opt-verbose add-of-ints.js
或
node --trace-opt-verbose add-of-ints.js
输出结果为:
从输出结果我们可以看到 add 函数被编译器优化了,并且解释了优化的原因。ICs 是 inline caches 的缩写,内联缓存是一种很常见的优化技术,这段简短的代码被 V8 引擎优化了两次,但是原因却不同。
第一次优化的原因是 small function,add 函数是小函数,为了减小函数调用的开销,V8 引擎对 add 做了优化。
第二次的原因是 hot and stable,我在知乎另一个问题中曾说过,V8 有两个编译器,一个通用编译器,负责将 javascript 代码编译为机器码,另一个是优化编译器。从上面的输出可以看出 V8 使用的优化编译器引擎是 Crankshaft。Crankshaft 负责找出经常被调用的代码,做内联缓存优化,后面的信息进一步说明了这个情况:ICs with typeinfo: 7/7 (100%), generic ICs: 0/7 (0%)。
在此再纠正之前的 2 个问题。
一个是 V8 没有解释器,只有编译器,代码是直接编译成机器吗执行的,这是之前的 V8,而网络上关于 V8 的文章也大多比较老旧。这几天为了阅读 V8 源码查看了网上很多关于 V8 的论文和文章,发现 V8 已经引进了解释器。因为 V8 不仅仅可以优化光棍影院代码,还可以去优化(deopt),引入解释器可以省去一些代码的重编译时间,另一个原因是解释器不仅仅可以解释 javascript 代码,还可以解释 asm 或者其他二进制中间码。
另一个错误就是关于 V8 优化的,之前写过 JavaScript 函数式编程存在性能问题么? 中道:
永远不可能被优化的有:
Functions that contain a debugger statement
Functions that call literally eval()
Functions that contain a with statement
这个也是之前的文章,是以 Crankshaft 引擎为标准得出的结论。而 V8 已经开发了新的优化引擎——TurboFan。
我们再创建另一个文件 add-of-mixed.js,输入:
// flag: --trace-opt-verbose
function add(obj) {
return obj.prop + obj.prop;
}
var length = 1000 * 1000;
var objs = new Array(length);
var i = 0;
for (i = 0; i < length; i++) {
objs[i] = Math.random();
}
var a = { prop: 'a' };
var b = { prop: 1 };
for (i = 0; i < length; i++) {
add(objs[i] > 0.5 ? a : b);
}
运行:
d8 --trace-opt-verbose add-of-mixed.js
或
node --trace-opt-verbose add-of-mixed.js
输出结果为:
可以看到这段代码能不能做内联缓存优化全看 RP(人品) 了。
我们再使用 --trace-opt --trace-deopt 参数看看 V8 引擎如何去优化。
新建文件 add-of-mixed-dep.js,输入:
// flags: --trace-opt --trace-deopt
function add(obj) {
return obj.prop + obj.prop;
}
var length = 10000;
var i = 0;
var a = { prop: 'a' };
var b = { prop: 1 };
for (i = 0; i < length; i++) {
add(i !== 8000 ? a : b);
}
运行:
d8 --trace-opt --trace-deopt add-of-mixed-dep.js
或
node --trace-opt --trace-deopt add-of-mixed-dep.js
结果为:
V8 引擎内部使用 Hidden Classes 来表示 Object,关于 Hidden Classes 的文章已经很多了,我就不累述了。
运行 d8 --help 可以查看所有的 d8 命令行参数。如果使用 node,直接运行 node --help 输出的是 node 的命令行参数,如果想查看 V8 的,需要使用 node --v8-options。
后面章节会介绍 V8 的 GC(命令行参数 --trace-gc)以及最有意思的 --allow-natives-syntax。
推荐阅读一下 V8 的 bailout-reason.h 源码,这是一个 C++ 的头文件,里面几乎没有任何代码逻辑新视觉,定义了所有 javascript 代码不能被 V8 引擎优化的原因,比如:
"Array index constant value too big"
"eval"
"ForOfStatement"
"Too many parameters"
"WithStatement"
……
后面章节介绍的 --allow-natives-syntax 相关 C++ 头文件是 runtime.h,通过 --allow-natives-syntax 参数可以在 javascript 中使用 V8 的运行时函数。我们在之前的文章中已经使用过了,例如 HasFastProperties。
使用 D8 分析 javascript 如何被 V8 引擎优化的的更多相关文章
- JavaScript深入浅出第4课:V8引擎是如何工作的?
摘要: 性能彪悍的V8引擎. <JavaScript深入浅出>系列: JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼? JavaScript深入浅出第2课:函数是一等 ...
- v8引擎详解(摘)-- V8引擎是一个JavaScript引擎实现
随着Web相关技术的发展,JavaScript所要承担的工作也越来越多,早就超越了“表单验证”的范畴,这就更需要快速的解析和执行JavaScript脚本.V8引擎就是为解决这一问题而生,在node中也 ...
- V8引擎——详解
前言 JavaScript绝对是最火的编程语言之一,一直具有很大的用户群,随着在服务端的使用(NodeJs),更是爆发了极强的生命力.编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进 ...
- v8引擎详解
引用网址: https://blog.csdn.net/swimming_in_it_/article/details/78869549 前言 JavaScript绝对是最火的编程语言之一,一直具有很 ...
- Node.js和Chrome V8 引擎了解
说起Node就不得不先介绍一个Chrome V8 引擎. 随着Web相关技术的发展,JavaScript所要承担的工作也越来越多,早就超越了“表单验证”的范畴,这就更需要快速的解析和执行JavaScr ...
- JavaScript是如何工作的02:深入V8引擎&编写优化代码的5个技巧
概述 JavaScript引擎是执行 JavaScript 代码的程序或解释器.JavaScript引擎可以实现为标准解释器,或者以某种形式将JavaScript编译为字节码的即时编译器. 以为实现J ...
- JavaScript工作机制:V8 引擎内部机制及如何编写优化代码的5个诀窍
概述 JavaScript引擎是一个执行JavaScript代码的程序或解释器.JavaScript引擎可以被实现为标准解释器,或者实现为以某种形式将JavaScript编译为字节码的即时编译器. 下 ...
- How Javascript works (Javascript工作原理) (二) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧
个人总结: 一个Javascript引擎由一个标准解释程序,或者即时编译器来实现. 解释器(Interpreter): 解释一行,执行一行. 编译器(Compiler): 全部编译成机器码,统一执行. ...
- JavaScript(二)——在 V8 引擎中书写最优代码
概述 一个 JavaScript 引擎就是一个程序或者一个解释程序,它运行 JavaScript 代码.一个 JavaScript 引擎可以用标准解释程序或者即时编译器来实现,即时编译器即以某种形式把 ...
随机推荐
- Android 4.4及以后将内容布局延伸到状态栏
首先说明:该文章不是大家说的沉浸式状态栏,网上沉浸式状态栏的博客很多,搜索就有了! 该篇博客的主要目的就是为了将图片显示在状态栏上,让APP看起来更有型!如下图所示: 界面 这个界面的布局就是co ...
- Elasticsearch-分片原理2
Elasticsearch版本:6.0 一.Elasticsearch计算分片位置的公式 shard = hash(routing) % number_of_primary_shards 解释:rou ...
- Python+selenium之截图图片并保存截取的图片
本文转载:http://blog.csdn.net/u011541946/article/details/70141488 http://www.cnblogs.com/timsheng/archiv ...
- 【Windows 10 v1703】解决桌面出现Removable Storage Devices的问题
症状如下: 右键没有正常菜单,不能查看属性. 不能通过文件树找到这个文件夹. 出现原因不明. 暂时的解决方案: 右键,新建一个快捷方式.然后将快捷方式拖进垃圾桶,删除.这个文件夹将会被连带删除. 感谢 ...
- MovieReview—A dog's purpose(一只狗的使命)
Be Here Now A dog in the movie was reinc ...
- java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config
今天写SpringMvc时,遇到这样一个问题: java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config at org.sp ...
- UVA 714 Copying Books 抄书 (二分)
题意:把一个包含m个正整数的序列划分成k个非空的连续子序列.使得所有连续子序列的序列和Si的最大值尽量小. 二分,每次判断一下当前的值是否满足条件,然后修改区间.注意初始区间的范围,L应该为所有正整数 ...
- 2018.3.12 Leecode习题 给定一个整数数列,找出其中和为特定值的那两个数。
给定一个整数数列,找出其中和为特定值的那两个数. 你可以假设每个输入都只会有一种答案,同样的元素不能被重用. 示例: 给定 nums = [2, 7, 11, 15], target = 9; 因为 ...
- RabbitMQ 学习资料
https://www.rabbitmq.com/getstarted.html http://www.cnblogs.com/luxiaoxun/p/3918054.html http://back ...
- 微信小程序传值取值的几种方法
一,列表index下的取值 实现方式是:data-index="{{index}}"挖坑及e.currentTarget.dataset.index来填坑即可 1.1生成值 < ...