描述内存性能 - acelan86/chromeDevTools GitHub Wiki

[原文地址]https://developers.google.com/chrome-developer-tools/docs/heap-profiling?hl=zh-CN

这个教程描述了如何通过Heap(堆)审查器来发现应用的内存泄漏。

基本功能

获取一份快照

在Profiles标签页中,选择Take Heap Snapshot选项并点击开始:

快照在渲染处理内存中被初始化存储。它们一经要求就被转移到DevTools,在你点击快照的图标要求查看它的时候。在快照被加载并解析到DevTools后,快照标题下面显示的数字表示了可到达的Javascript对象占用的所有内存大小总和:

清除快照

通过点击Clear all profile按钮可以移除快照(在DevTools和渲染内存中的)。

注意:关闭DevTools窗口不能从渲染内存中删除收集的审查数据。当重新打开DevTools的时候,所有之前获取的快照会重新显示在快照列表中

切换快照视图

快照可以从不同的方面被展现以适应不同的任务。要在不同的视图中切换快照,使用视图底部的选项菜单:

有四种视图:

  • Summary — 通过构造器的名字分组显示对象。
  • Comparison — 显示两份快照之间的不同处;
  • Containment — 允许查看堆内容;
  • Dominators — 显示dominators树.

查看颜色编码的意义

对象的属性和特性值有不同的类型,并且根据这些类型被分色显示。要显示颜色图例,点击状态栏上面的问号按钮:

每一个属性是下面四种类型之一:

  • property — 一个带名字的普通属性,通过.(dot)操作符访问,或者通过[](brackets)访问。例如["foo bar"];
  • element — 一个带数字索引的普通属性,通过[](brackets)访问;
  • context variable — 在函数上下文中的一个变量,通过它在函数闭包中的名字访问;
  • system property — Javascript虚拟机添加的属性,无法通过Javascript代码访问。

被指派为System的对象没有对应的Javascript类型。他们是Javascript虚拟机的对象系统实现的一部分。

视图的细节

Summary视图

默认情况下,快照在Summary视图中打开,显示对象总和,它可以展开来显示实例:

顶级的实体是“total”行。他们显示了构造器的名字,并且包含了所有通过这个构造器创建的对象。对象实例的数量显示在#列。Shallow size列显示了所有通过某个构造函数创建的对象内存分配的大小总和。Retained Size列显示了同一对象集合中保持的最大的那个内存大小。

在上面的视图中展开total行后,它的所有实例都会被展现。对于每一个实例,它的分配和保持内存大小显示在对应的列中。在@字符后面的数字是对象的唯一ID,允许比较对象基准的堆快照。

试试这个演示页面(在新标签页中打开)来理解Summary视图能被用来做什么。

Comparison视图

当获取了多个堆快照的时候,你能够比较他们,然后找出泄漏的对象。要验证某个应用的操作没有产生泄漏(例如,通常一对直接和逆向操作,像打开一个文档,和关闭它,不会留下任何垃圾),你可以通过下面的方法:

  1. 在做一个操作前获取一份堆快照
  2. 进行一个操作(比如打开一个文档)
  3. 进行一个反向的操作(关闭一个文档)
  4. 获取一份堆快照

在Comparison视图中,两份快照中的不同会被显示。当展开一个total入口的时候,增加和删除的对象实例会被显示出来:

尝试这个演示页面(在新标签页中打开)来得到如何使用快照比较功能来检测内存泄漏的提示。

Containment视图

Containment视图本质上是一个你的应用的对象结构的“鹰眼视图” 。它允许你窥视函数闭包内部,来观察你的javascript对象创建的同时一起创建的虚拟机内部对象,且可以用于从底层了解你的应用使用了多少内存。

视图提供了多个入口点:

  • DOMWindow objects — 作为Javascript代码的“global”对象的对象。
  • GC roots — 虚拟机的内存回收器使用的实际GC根节点
  • Native objects — 被“pushed”到Javascript虚拟机自动创建的浏览器对象,例如DOM节点,CSS规则(详见下一部分内容)

下面是一个例子展示了Comtainment视图:

尝试这个演示页面(在新标签页中打开)来找出怎样通过这个视图来浏览闭包和事件句柄

发现DOM内存泄漏

新工具唯一的能力是反映出在浏览器本地对象(DOM节点,CSS规则)和Javascript对象间的双向依赖。它能够帮助发现由于忘记移除漂浮的DOM子树而产生的隐蔽的内存泄漏。

本地对象很容易通过Summary和Containment视图被访问 - 他们有专用的入口节点

尝试这个演示页面(在新标签页中打开)来演示分离DOM树。

Dominators视图

Dominators视图显示了堆图的dominators树。Dominators视图看起来和Containment视图相似,单缺少属性名。这是因为一个对象的dominator可能缺少指向它的直接的引用,也就是,dominators树不是堆图的一棵生成树。但这只是为good服务,作为帮助我们快速定位内存积累点。

尝试这个演示页面(在新的标签页中打开)来训练自己查找内存积累点。

保持路径

保持路径(retaining path)视图总是显示。要激活它,点击上面面板中的对象,忽视当前激活的视图。审查器将开始查找从根到选中对象的最简单的路径。它将从最短的路径开始,逐步增加步长。它可能约束根集合到DOMWindow对象,替代所有GC根节点。这有助于我们发现从应用自己内部发现原始引用 -他们最可能是泄漏的源头:

在最简单的情况下,路径值包含“true”Javascript对象和用于从Javascript代码中访问的引用,例如:

如果进入适当的上下文中,这样的路径可以很容易的在debugger控制台中获得结果。(例如,如果一个应用有若干个iframes,在执行属于他们的函数代码的时候执行过程会被挂起)。求一条路径使得它能够检查每个对象完整的内容,包括那些没有在堆中存储值的属性,且这些无法在快照中被捕捉到。

对象通过闭包被保持的情况时有发生。闭包引用通过->符号显示:

这样的路径不能在控制台中获得结果。

更高级的是一些包含“hidden”对象的路径。通常,这些路径的存在不是意味着应用有内存泄漏。有些路径是“低级的”路径,等价于他们的Javascript快捷引用。例如,每一个对象有元素和属性内部数组,因此一个属性值可以被显示成直接通过一个对象保持(这是Javascript编程者如何看到它),或者作为属性数组的一个元素(这是Javascript虚拟机实际如何访问它),知道这些细节可以帮助你理解虚拟机如何工作。尽管如此,对于更多的web应用开发者来说,忽略他们可能会更安全。下面是一些“内部”路径的例子:

问答

你们懂的,我懒了,看原文吧