热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用D8分析javascript如何被V8引擎优化的

在上一篇文章中我们讲了如何使用GN编译V8源码,文章最后编译完成的可执行文件并不是V8,而是D8。这篇我们讲一下如何使用D8调试javascript代码。如果没有d8,可以使用node代替。新建文件 add-of-ints.js,输入以下内容:functionadd(obj){returnobj.prop+obj.pr

在上一篇文章中我们讲了如何使用 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 

运行:

d8 --trace-opt-verbose add-of-ints.js
或
node --trace-opt-verbose add-of-ints.js

输出结果为:

使用 D8 分析 Javascript 如何被 V8 引擎优化的

从输出结果我们可以看到 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 Math.random();
}

var a = { prop: 'a' };
var b = { prop: 1 };

for (i = 0; i  0.5 ? a : b);

}

运行:

d8 --trace-opt-verbose add-of-mixed.js
或
node --trace-opt-verbose add-of-mixed.js

输出结果为:

使用 D8 分析 Javascript 如何被 V8 引擎优化的

使用 D8 分析 Javascript 如何被 V8 引擎优化的

可以看到这段代码能不能做内联缓存优化全看 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 8000 ? a : b);

}

运行:

d8 --trace-opt --trace-deopt add-of-mixed-dep.js
或
node --trace-opt --trace-deopt add-of-mixed-dep.js

结果为:

使用 D8 分析 Javascript 如何被 V8 引擎优化的

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


推荐阅读
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 本文将介绍如何使用 Go 语言编写和运行一个简单的“Hello, World!”程序。内容涵盖开发环境配置、代码结构解析及执行步骤。 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
  • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • CMake跨平台开发实践
    本文介绍如何使用CMake支持不同平台的代码编译。通过一个简单的示例,我们将展示如何编写CMakeLists.txt以适应Linux和Windows平台,并实现跨平台的函数调用。 ... [详细]
  • 本文详细介绍了如何通过多种编程语言(如PHP、JSP)实现网站与MySQL数据库的连接,包括创建数据库、表的基本操作,以及数据的读取和写入方法。 ... [详细]
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
author-avatar
DarkBaron_
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有