摘要:当我们在中查看代码的调用栈时,这些函数是被过滤掉的。当我们捕获调用栈时,并不会捕获写的函数。不过,在引擎中很多原生函数都是使用语言编写的。如果我们开启设置,将会在中显示这些函数。分析器也会不一致。
本文翻译自 Chrome DevTools: Show native functions in JS Profile,中文版首发在我的知乎专栏 V8 源码及周边。
在 Chrome DevTools 中可以使用 profiler 查看原生函数的执行性能:
原生函数(native function)是 JavaScript 语言的一部分,这些函数有别于开发者编写的自定义函数。当我们在 profiler 中查看代码的调用栈时,这些函数是被过滤掉的。我们在 profiler 中看到的只有自己写的代码。
当我们捕获调用栈时,Chrome 并不会捕获 C++ 写的函数。不过,在 V8 引擎中很多 javascript 原生函数都是使用 javascript 语言编写的。
V8 使用 JavaScript 本身实现了 JavaScript 语言的大部分内置对象和函数。 例如,promise 功能就是通过 JavaScript 编写的。我们把这样的内置函数称为自主托管(self-hosted)。
如果我们开启 “Show native functions” 设置,Chrome 将会在 profiler 中显示这些函数。
Chrome 分析器是如何工作的为了找到那些耗时最多的代码,Chrome 分析器每 100μs 捕获一个堆栈跟踪。
这意味着,如果一个函数只需要 50μs 的执行时间,就可能不会在分析器中显示出来!
当你分析几毫秒以上的时间时,可以准确了解应用程序在何时花费最多的时间。 但是,当你放大 profiler 面板想看更精准的时间时,信息会变得不太准确。
分析器也会不一致。 每次运行时,会产生一个稍微不同的结果。 有时可能会记录非常短的函数调用,而在其他时间再次运行这些函数调用信息可能会丢失。
通过这篇博客文章我将为大家演示如何捕获并分析原生函数的性能。当你自己运行代码时,结果可能会有所不同。
Array.join首先,我们运行如下代码:
var arr = [] for (var i=0; i<1000; i++){ arr.push(i) } console.profile("Array.join") arr.join(",") console.profileEnd("Array.join")
选择 profiler 的 “Chart” 视图:
第一次分析时,我们不选中 “Show native functions”:
我们再次运行时,把 “Show native functions” 启用:
当我们把鼠标指向函数时,会看到更加详细的信息:
如上信息中,chrome devtools 展示了原生函数的行号,你可以在 Chrome code search中找到这个文件 “array.js”。行号信息可能不同,因为 V8 源码的最新版本和 Chrome 使用的 V8 版本可能不一样。
你可以看到 ArrayJoin 函数在内部调用了 InnerArrayJoin:
function ArrayJoin(separator) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join"); var array = TO_OBJECT(this); var length = TO_LENGTH(array.length); return InnerArrayJoin(separator, array, length); }
InnerArrayJoin 在内部调用了 DoJoin。
DoJoin 调用了 %StringBuilderJoin。
%StringBuilderJoin 是使用 C++ 实现的。
稀疏数组我们有点偏离主题,但是我认为 V8 处理稀疏数组(new Array(n))是非常有趣的。
为什么这很有用呢?下面的代码是如何运行的?
arr = new Array(10000000) for (var i=0; i<10000; i++){ arr.push(i) } console.profile("arr + arr") arr + arr console.profileEnd("arr + arr")
您通常不会在两个数组上执行加操作。但是由于某种原因,我最近看过的一些代码就是这样做的。
当不是用查看原生函数时,我们看到了一个匿名函数的调用。
当我们开启了查看原生函数功能时,Chrome 调用了 array 的 toString 方法,然后调用了 join 方法。
Error().stack我们来看一个不同的例子。在 JavaScript 中,您可以使用 Error().stack 获取当前正在运行的函数的堆栈跟踪(stack trace)。
当我们运行该代码时,一共做了两件事: 首先我们创建一个新的 Error 对象,然后访问它的 stack 属性。
获取堆栈跟踪的字符串描述信息时,耗费了大量的时间。
我能够通过获取一个 Error 对象来加快我正在处理的代码:只有当我需要显示堆栈跟踪时,才解析其 stack 属性。
不准确的地方在我的文章的开头章节,我提到了非常小的时间间隔可能造成结果的不准确。为了说明这一点,我在另一台不同配置的电脑上运行了 Error().stack 的代码段。
我们看到了 FormatErrorString 函数,而在之前的分析中,这个函数并没有显示出来。
(这次的总执行时间是 ~1ms,这意味着 Chrome 需要 10 个调用堆栈的样本。上面的例子花了 ~10ms,因为我在循环中调用了 10 次 Error().stack。)
相关阅读移动 Web 滚动性能优化:Passive Event Listeners
使用 D8 分析 javascript 如何被 V8 引擎优化的
开启 V8 对象属性的“fast”模式
这几天 SF 增加了新的板块——直播。我也收到了官方的邀请。4月15(星期六)晚8点和大家一起聊聊 V8 引擎:前端程序员应该懂点 V8 知识 - SegmentFault 讲堂。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/82237.html
摘要:实现不定期更新技巧前端掘金技巧,偶尔更新。统一播放效果实现打字效果动画前端掘金前端开源项目周报前端掘金由出品的前端开源项目周报第四期来啦。 Web 推送技术 - 掘金腾讯云技术社区-掘金主页持续为大家呈现云计算技术文章,欢迎大家关注! 作者:villainthr 摘自 前端小吉米 伴随着今年 Google I/O 大会的召开,一个很火的概念--Progressive Web Apps ...
摘要:我打算把一些上使用的高级技巧写成你不知道的这一系列的博文,希望大家一起学习学习。在代码中使用的最简单的用法就是写个在控制台打印一行消息。跟的区别在于会对输出的对象进行展开。用于显示一组的控制台输出,要搭配来使用。 Web前端开发过程中必然会用到Chrome浏览器自带的开发者工具Chrome DevTools,使用它作为Web前端开发性能调试的必备工具。就连隔壁的产品小哥都知道打开F12...
摘要:对于每个前端程序员来讲都有一个终极理想,那就是搞懂引擎是如何工作的。性能经过了两次飞跃第次飞跃是年发布,第次则是年的。从去年底开始连载源码分析,记录一下自己学习源码的点点滴滴。月星期六晚点和大家一起聊聊引擎前端程序员应该懂点知识讲堂。 对于每个前端程序员来讲都有一个终极理想,那就是搞懂 javascript 引擎是如何工作的。 从我的网络 ID(justjavac)可以看出来,当我开始...
摘要:是一个网页版的小工具,可以用全新的方式展示性能分析的结果,帮助开发者洞悉函数调用关系,优化应用性能。研究表明这个数字正对应于的值。因此知道了路径编号,便可以知道那些函数处在激活状态。在中用蓝色表示。 OneProfile 是一个网页版的小工具,可以用全新的方式展示 JavaScript 性能分析的结果,帮助开发者洞悉函数调用关系,优化应用性能。 点击打开 OneProfile...
1、Chrome控制台小技巧 打开和关闭抽屉式选项卡:按Esc键可打开和关闭 DevTools 的 Drawer(抽屉式选项卡) 在Drawer(抽屉式选项卡)中,你可以在 Console 控制台中执行命令,查看动画检查器(Animations),配置网络条件(network conditions)和渲染(rendering)设置,搜索(search)字符串和文件等 showImg(https...
阅读 1074·2021-11-22 14:56
阅读 1519·2019-08-30 15:55
阅读 3358·2019-08-30 15:45
阅读 1654·2019-08-30 13:03
阅读 2867·2019-08-29 18:47
阅读 3332·2019-08-29 11:09
阅读 2640·2019-08-26 18:36
阅读 2614·2019-08-26 13:55