若是上篇中的Timeline面板所提供的信息不能知足你的要求,你可使用Profiles面板,利用这个面板你能够追踪网页程序的内存泄漏问题,进一步提高程序的JavaScript执行性能。javascript
当前使用的Chrome最新版为54.0.2840.71,这个版本的Profiles面板比以前提供的功能更多也更强大,下面是该面板所包含的功能点:java
经过选择Record JavaScript CPU Profile,而后点击Start,结合你所要分析的具体场景,你能够从新加载网页,或者在网页上进行交互,甚至什么都不操做。最后点击Stop,完成记录操做。正则表达式
有三种不一样的视图可供选择:chrome
咱们以Chart视图为例分析一下JS的执行的性能状况:数组
该视图会以时间顺序展现CPU的性能状况,视图主要分红两块:浏览器
视图中的函数颜色不一样于其它的面板,这里面的函数颜色标记是随机显示的。然而相同的函数调用颜色标记是相同的。缓存
其中纵轴表示的函数调用堆栈高度仅仅函数的调用嵌套层次比较深,不表示其重要性很高,可是横轴上一个很宽的柱形条则意味着函数的调用须要一个很长的时间去完成,那么你就考虑去作一些优化操做,具体能够参见网络性能优化方案及里面的相关参考文档。性能优化
将鼠标移到Call Stacks中的函数上能够显示函数的名称和时间相关的数据,会提供以下信息:网络
经过建立堆快照能够查看建立快照时网页上的JS对象和DOM节点的内存分布状况。利用该工具你能够建立JS的堆快照、内存分析图、对比堆快照以及定位内存泄漏问题。选中Take Heap Snapshot,点击Take Snapshot按钮便可获取快照,在每一次获取快照前都会自动执行垃圾回收操做。闭包
快照最初会存储在渲染进程的内存之中,当咱们点击建立快照按钮来查看时才会被传输到DevTools中,当快照被加载到DevTools里面并通过解析以后,在快照标题下方的文字显示是数字就是可访问到的JS对象总的大小。
堆快照提供了不一样的视角来进行查看:
该视图会显示全部的对象信息,点击其中的一个对象进行展开可查看更详细的实例信息。鼠标移动到某个对象上会显示该对象实例的详情信息。
图中的各列的具体含义以下:
Shallow size和Retained size的区别?Shallow size是对象自己占用内存的大小,不包含它所引用的对象。Retained size是该对象自己的Shallow size,加上能从该对象直接或者间接访问到对象的Shallow size之和。也就是说Retained size是该对象被GC以后所能回收到内存的总和。
在展开构造函数,则会列出该函数相关的全部对象实例,能够查看该对象的Shallow size和Retained size,在@符号后面的数字是该对象的惟一标识ID。
其中黄色的对象表示在它被某个JS所引用,而红色的对象表示由黄色背景色引用被分离开出的节点。
这些构造函数都表明什么含义呢?
window
)和经过它引用的对象之间的中间对象,若是一个对象是由Person构造函数生成并被全局对象所引用,那么它们的引用路径关系就像这样[global] > (global property) > Person。这跟常规的对象之间直接引用相比,采用中间对象主要是考虑性能的缘由。全局对象的改变是很频繁的,而非全局变量的属性访问最优化方案对全局变量是不适用的。经过比较多个快照之间的差别来找出内存泄露的对象,为了验证某个程序的操做不会引发内存泄露(一般会执行一个操做后再执行一个对应的相反操做,好比打开一个文档后再关闭它,应该是没有产生内存泄露问题的),你能够执行以下步骤:
切换到Comparison视图以后,就能够看到两个不一样的快照之间的差异。
该视图本质上就是应用程序的对象结构的“鸟瞰图”,容许你去深刻分析函数的闭包,了解应用程序底层的内存使用状况。
这个视图提供了多个入口:
闭包小建议: 在快照的分析中命名函数的闭包相比匿名函数的闭包更容易区分。
Google上提供的例子和图以下:
function createLargeClosure() { var largeStr = new Array(1000000).join('x'); var lC = function() { // 匿名函数 return largeStr; }; return lC; }
function createLargeClosure() { var largeStr = new Array(1000000).join('x'); var lC = function lC() { // 命名函数 return largeStr; }; return lC; }
该视图是堆快照的总的分布统计状况,这个直接上图就能够了:
仍是把Google提供的内存泄露的小例子贴出来:
DOM内存泄露可能比你想象的要大,考虑一下下面的例子-何时#tree节点被释放掉?
var select = document.querySelector; var treeRef = select("#tree"); var leafRef = select("#leaf"); var body = select("body"); body.removeChild(treeRef); //因为treeRef #tree不能被释放 treeRef = null; //因为leafRef的间接引用 #tree仍是不能被释放 leafRef = null; //如今没有被引用,#tree这个时候才能够被释放了
#leaf
节点保持着对它的父节点(parentNode)的引用,这样一直递归引用了#tree
节点,因此只有当leafRef
被设置成null后,#tree
下面的整个树节点才有可能被垃圾回收器回收。
该工具是能够帮助你追踪JS堆里面的内存泄漏的另外一大利器。
选中Record Allocation Timeline按钮,点击Start按钮以后,执行你认为可能会引发内存泄漏的操做,操做以后点击左上角的中止按钮便可。你能够在蓝色竖线上经过缩放来过滤构造器窗格来仅仅显示在指定的时间帧内的被分配的对象。
录制过程当中,在时间线上会出现一些蓝色竖条,这些蓝色竖条表明一个新的内存分配,这个新的内存分配均可以会有潜在的内存泄露问题。
经过展开对象并点击它的值则能够在Object窗格中查看更多新分配的对象细节。
从JS函数角度记录并查看内存的分配信息。点击Start按钮,执行你想要去深刻分析的页面操做,当你完成你的操做后点击Stop按钮。而后会显示一个按JS函数进行内存分配的分解图,默认的视图是Heavy (Bottom Up),该视图会把最消耗内存的函数显示在最顶端。
下图是切换到Chart视图时具体的界面,点击任意函数跳转到Sources面板能够查看具体的函数信息。