当前位置:K88软件开发文章中心编程工具Chrome → 文章内容

Chrome开发工具 JavaScript 内存分析

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-24 11:01:34

由 珍珍阿姨 创建,Loen 最后一次修改 2016-08-12 JavaScript 内存分析内存泄露是指计算机内存逐渐丢失。当某个程序总是无法释放内存时,就会出现内存泄露。JavaScript web 应用程序可能会经常遇到类似于本地程序中内存泄露这样的问题,比如泄露和膨胀,但是 JavaScript 有内存回收机制可以解决此类问题。尽管 JavaScript 使用了内存回收机来自动管理内存,高效的内存管理策略依然是相当重要的。在本章中我们会详细说明 JavaScript web 应用程序中的内存问题。在学习某些特性的时候请尝试这些示例,这可以增进你对于工具运行原理的认识。在开始之前,请查看 Memory 101 页面来熟悉一下相关的专业术语。注意:我们在后面使用的有些特性是只有 Chrome Canary 才支持的。我们建议使用此版本的工具,这样您就可以对您的应用程序做出最佳的内存分析。应该问自己的一些问题通常情况下,当你认为你的程序出现内存泄露的时候,你需要问自己三个问题:是不是我的页面占用了太多的内存?- 内存时间轴视图 以及 Chrome 任务管理器 可以帮助你来确认是否占用了过多的内存。内存视图在监察过程中可以实时跟踪 DOM 节点数目、文件以及 JS 事件监听器。有一条重要法则需要记住:避免保留对已经不需要的 DOM 元素的引用,不必要的事件监听器请解除绑定,对于大量的数据,在存储时请注意不要存储用不到的数据。我的页面是不是没有内存泄露的问题?- 对象分配跟踪器能够让你看到 JS 对象的实时分配过程,以此来降低内存泄露的可能。你也可以使用堆探查器来记录 JS 堆的状态,然后分析内存图并将其与堆状态进行比对,就可以迅速发现那些没有被垃圾回收器清理的对象。我的页面应该多久强制进行一次垃圾回收? - 如果垃圾回收器总是处于垃圾回收状态,那么可能是你对象分配过于频繁了。内存时间轴视图可以在你感兴趣的地方停顿,方便你查看回收情况。视图内容术语以及基本原理这个部分介绍了内存分析中常见的术语,即使是在其他语言的内存分析工具中,这些术语也同样有用。这里所说的术语和概念是用于堆探查器界面以及相应文档中的。了解这些术语后,你们就能更加高效地使用这个工具。如果你曾经使用 Java、.Net 或者其它内存分析器,那么该篇的内容对你而言就是一次提升。对象的大小请将内存状况想象为一副图片,图中有着一些基本类型(像是数字以及字符串等)和对象(关联数组)。如果像下面这样将图中的内容用一些相互连接的点来表示,可能有助于你对此的理解:对象可以通过两种方式来获取内存:直接通过它本身。通过包含对其它对象的引用,这样就会阻止垃圾回收器(简称 GC)自动回收这些对象。当使用 DevTools 中的堆分析器(一种用于查找“配置文件”下的内存问题的工具)的时候,你会发现你所看到的是几列信息。其中最重要的就是 Shallow Size 以及 Retained Size,不过,这两列究竟意味着什么呢?Shallow size这是指对象本身获得的内存大小。典型的 JavaScript 对象会获得一些保留的内存,用于他们的描述以及存储即时产生的值。通常情况下,只有数组和字符串才会有比较明显的浅层大小。不过,字符串和外部数组往往在渲染内存中有它们自己的主存储器,对 JavaScript 堆只露出一点包装后的对象。渲染内存是指所监视的页面被渲染的过程中使用的内存:原本分配的内存 + 该页面在 JS 堆中的内存 + 所有因为该页面而导致的 JS 堆中其他对象的内存开销。然而,即使是一个小的对象也可以通过阻止垃圾回收器自动回收其他对象来间接保有大量的内存。Retained size这是指对象以及其相关的对象一起被删除后所释放的内存大小,并且 GC roots 无法到达该处。GC roots 是由在从原生代码的 V8 之外引用 JavaScript 对象的时候所创建的句柄(局部或者全局的)构成的。这些句柄可以再堆的快照中 GC roots > Handle scope 以及 GC roots > Global handles 中找到。在没有谈及浏览器实现的细节的情况下,就在本文中说明句柄会令读者感到困惑,故而关于句柄的细节本文不做讲解。事实上,无论 GC roots 还是句柄,都不是你需要担心的东西。内部的 GC roots 有很多,不过用户对其中的大部分都不感兴趣。从应用程序的角度来说,有下面这么几种 roots:窗口全局对象(在每一帧中)。在堆快照中,有一个距离域,其包含的是在窗口最短保留路径上的属性引用的数目。文档 DOM 树是由所有分析该文档时能够到达的 DOM 节点构成的。并不是所有的节点都会有 JS 封装,但是如果他们有封装,那么只要文档还在,这些节点就可以使用。有些时候,对象会被调试器上下文以及 DevTools 控制台保留。(例如,在控制台进行评估后)注意:我们推荐读者在清空控制台并且调试器中没有活跃的断点的情况下来做堆的快照。下面的内存就是由一个根节点开始的,这个根节点可能是浏览器的 window 对象或者是 Node.js 模块的 Global 对象。你并不需要知道这个对象是如何被回收的。任何无法被根节点取得的元素够将被回收。提示:Shallow 和 Retained size 都用字节来表示数据。对象的保留树就像我们前面所说的,堆就是由相互连接的对象构成的网络。在数学的世界中,这种结构称作图或者内存图。一个图是由节点和边构成的,而节点又是由边连接起来的,其中节点和边都有相应的标签。节点(或者对象)是用创建对象的构造函数标记的。边是用属性名来标记的。在本文后面的内容中,你将会学到如何使用堆探查器来记录资料。在堆分析器记录中我们可以看到包括 Distance 在内的几栏:Distance 指的是从根节点到当前节点的距离。有一种情况是值得探究的,那就是几乎所有同类的对象都有着相同的距离,但是有一小部分对象的 Distance 的值要比其他对象大一些。主导者主导者对象是由树形结构组成的,因为每个对象都只有一个主导者。一个对象的支配者不一定直接引用它所主导的对象,也就是说,支配树并不是图的生成树。在上面的图中:节点 1 主导了节点 2.节点 2 主导了节点 3,4,6节点 3 主导了节点 5节点 5 主导了节点 8节点 6 主导了节点 7在下面的例子中,节点 #3 是 #10 的主导者,但是 #7 节点也在由 GC 到 #10 节点的,每条简单路径上。因此,如果对象 B 存在于从根节点到对象 A 的,每条简单路径上,那么对象 B 就是对象 A 的主导者。V8

[1] [2] [3] [4] [5]  下一页


Chrome开发工具 JavaScript 内存分析