by addy 原创文章,欢迎转载,但希望全文转载,注明本文地址。

本文地址:https://www.iamaddy.net/2017/06/chrome-dev-tools-profiles/

内存快照工具

profiles的翻译是轮廓的意思,在chrome中可以理解为程序内部剖面的意思。就是可以看到内部到底是怎么运转的。
最新版本的开发工具已经改名为Memory,右侧我们可以看到profiles,这里的意思是内存的一个剖面分析。

右侧我们可以分析三种类型的选择。第一个是堆的快照,最下面的按钮是可以加载之前已经记录的文件。
chrome开发工具系列—— Profiles篇我们点击Take Snapshot,开始采集堆的快照。采集完成后会生成一个文件,我们可以保存。当然当你想看看你在页面进行了一些操作,导致的快照变化,我们可以采集多个快照。

那么什么是JS的堆栈呢?

JS运行的时候,会有栈内存(stack)和堆内存(heap),当我们用new实例化一个类的时候,这个new出来的对象就保存在heap里面,而这个对象的引用则存储在stack里。程序通过stack里的引用找到这个对象。

例如var a = [1,2,3];,a是存储在stack里的引用,heap里存储着内容为[1,2,3]的Array对象。

chrome开发工具系列—— Profiles篇

上面表格的顶部那些名词可能有点陌生,我们依次来看下:

  • Constructor — 类名

  • Distance — 对象到根的层级距离

  • Objects Count — 当前有多少个该类的对象

  • Shallow Size — 对象所占内存(不包含内部引用的其它对象所占的内存)(单位:字节)

  • Retained Size — 对象所占总内存(包含内部引用的其它对象所占的内存)(单位:字节)

这样可能就会更清楚了吧。那我们展开其中一个看看里面有什么东西。Window这个全局对象下面的东西可以不少,那么像removeClass、trim等等,这就是我们代码中的全局变量。选中每一个变量,可以展开其下面的详细信息,包括引用的次数,占用的大小。

chrome开发工具系列—— Profiles篇

选中单个快照文件,可以看堆的大小的饼图,看看哪些类型占了更多的空间。

chrome开发工具系列—— Profiles篇

内存的快照

如果你不太明白,我建议你亲自写代码体验下,可以参照我讲解的例子。
定义以下函数和变量:

chrome开发工具系列—— Profiles篇

addyxu是一个函数,64051是系统分配了的一个堆的编号,可以理解为指针指向的地址,其下面的原型都会有一个编号。

chrome开发工具系列—— Profiles篇

addyxuInstance 是addyxu类的一个实例,我们可以看到构造函数指向了addyxu,并且编号就是同一个地址。

chrome开发工具系列—— Profiles篇

addyxuArr 是一个数组,而addyxuObject是一个对象,addyxuStr是一个字符串。我们可以看到这三种类型的变量在内存中的表示是不太一样的。elements是数组的元素集合,数组有一个原型proto,原型指向的是Array这个类型,包括了所有数组的一个熟悉方法。同样对象也是,但它还有熟悉名name。

chrome开发工具系列—— Profiles篇

我们来看一个更深一点的例子,下面这段代码一般有点开发经验的读看得懂。但能说的出输出的结果吗?
那么我们可以从堆的快照来分析下

chrome开发工具系列—— Profiles篇

chrome的面板有搜索功能,搜索上面定义的对象。我们发现可以搜到两个定义的类,他们的指向是不一样的。

chrome开发工具系列—— Profiles篇

选中第一个,我们发现有一个实例bbbb。

chrome开发工具系列—— Profiles篇

同样,选中第二个,我们发现有一个实例aaaa。

chrome开发工具系列—— Profiles篇

所以上面连个实例化后的对象实际的指向是不一样了。所以最后的输出结果你知道是什么了吗?

知道为什么会这样吗?为什么MyObj被重写了,原来的原型还保留着。因为原来的原型还有aaaa实例对他的引用呀,所以内存是不会回收第一次定义的那块空间。那么有些代码写的不好,会导致对象回收不及时,造成内存泄露,大家常说的就是dom元素导致泄露。

dom元素与内存

chrome开发工具系列—— Profiles篇

这个图的意思是这样的:

红色的节点表示仍然存在的分离DOM树的一部分,并且DOM树中的某个节点仍然在被JavaScript引用(可能是一个闭包或者某些属性)

黄色的节点表示一个分离DOM树的引用,可能是某个对象的属性或者是一个数组元素,在元素和window之间可能存在着一条属性链(例如 window.a)

那么写什么样的代码会导致上面的两种情况:

chrome开发工具系列—— Profiles篇

chrome开发工具系列—— Profiles篇

chrome开发工具系列—— Profiles篇

红色呢?

chrome开发工具系列—— Profiles篇

chrome开发工具系列—— Profiles篇

与黄色的区别在哪?被删除的元素的子节点test被变量a保持引用。这样导致span无法回收,除非a被销毁。

以上,希望能够帮助大家更好的理解JavaScript的堆栈。

本文为原创文章,可能会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,谢谢合作

本文地址:https://www.iamaddy.net/2017/06/chrome-dev-tools-profiles/

个人知乎,欢迎关注:https://www.zhihu.com/people/iamaddy

欢迎关注公众号【入门游戏开发】 入门游戏开发