前端层面性能调优——内存泄漏

内存泄漏

一些不会用到的内存没被及时释放即可造成内存泄漏。例如某些变量已经使用完但是还存在引用,垃圾回收机制不能回收,造成了内存泄漏。

识别内存泄漏

浏览器;命令行:

  1. 浏览器 :开发者工具——>memory,
    ·先进行垃圾回收,再点击录制(如果是JS堆内存动态分配时间线,结束前需再次点击垃圾回收)。
    ·Summary总览视图:按构造函数分组。用于捕捉对象及其使用的内存。对于定位DOM内存泄露特别有用。
    在这里插入图风格片描述
    悬浮查看:
    Constructor—构造函数,节点下的对象都是由改构造函数创建而来。
    Distance—与根节点的距离。
    Objects Count—对象个数及百分占比。
    Shallow size—对象的直接内存总数,直接内存是指对象自身占用的内存大小。
    Retained size—对象的最大保留内存,保留内存是指对象被删除后可以释放的那部分内存。
    点击展开构造函数,可以看到所有构造函数相关的对象实例,@后面的数字是该对象实例的唯一标识符。

常见的顶层构造函数:
(global property):全局对象和普通对象的中间对象,和常规思路不同。比如在Window上定义了一个Person对象,那么他们之间的关系就是[global] => (global property) => Person。之所以使用中间对象,是出于性能的考虑。
(closure):使用函数闭包的对象。
(array, string, number, regexp):一系列对象类型,其属性指向Array/String/Number/Regexp。
HTMLDivElement/HTMLAnchorElement/DocumentFragment:元素的引用或者代码引用的指定文档对象。

·Containment 内容视图:查看堆内容。更适合查看对象结构,有助于分析对象的引用情况。适用于分析闭包以及深入分析对象。其实就是应用对象结构的鸟瞰图。它能让你深入分析函数闭包,观察VM内部对象,查看应用底层的内存使用情况。

·Comparison对比视图:对比两个快照。用于对比不同操作之后的堆快照,查看内存的释放及引用计数,来分析内存是否泄露及其原因。
1、无任何操作,拍第一个堆快照
2、执行你觉得可能造成内存泄露的操作,再执行相反操作
3、拍第二个堆快照,切换到对照视图,并且指定与第一个堆快照对比

·Statistics 统计视图:总览堆的统计信息。

*JS堆分配时间线:通过Allocation instrumentation on timeline可以持续的记录堆分配的情况,显示了对象在什么时候被创建、什么时候存在内存泄漏等。柱条表示堆中生成的新对象。高度表示这个对象的大小,颜色表示这个对象的内存释放情况:蓝色柱表示这个对象在timeline中生成,结束前仍然存在;灰色柱表示这个对象在timeline中生成,但结束前已经被回收了。
我们可以重复执行某个动作,如果最后有不少蓝色柱被保留,这些蓝色柱就是潜在的内存泄露问题。
如果左边的意料之外的蓝条,那么极有可能存在内存泄露。

  1. 命令行 :;
    命令行可以使用 Node 提供的process.memoryUsage方法。
    process.memoryUsage返回一个对象,包含了 Node 进程的内存占用信息。该对象包含四个字段,单位是字节,含义如下。
    在这里插入图片描述
    ·rss(resident set size):所有内存占用,包括指令区和堆栈。
    ·heapTotal:"堆"占用的内存,包括用到的和没用到的。
    ·heapUsed:用到的堆的部分。
    ·external: V8 引擎内部的 C++ 对象占用的内存。

判断内存泄漏,以heapUsed字段为准。

  1. 浏览器 :开发者工具——>Performance(低版本是Timeline,高版本对应Performance)
    Performance(时间轴)面板直观实时显示JS内存使用情况、节点数量、监听器数量等。
  • 打开控制台上的(时间轴)面板。
  • 启用Memory(内存)复选框。
  • 开始录制前先点击垃圾回收–>点击开始录制–>点击垃圾回收–>点击结束录制
    你也可以保存录制时间轴或上传以前保存的时间轴
    在这里插入图片描述

这个界面由上往下分别是:

  • Overview的HEAP(堆)曲线图表示JS堆。
  • Call Stack通常来说,垂直方向并没有太大的意义,仅仅表示函数嵌套比较深而已,但是横向表示调用时间,如果调用时间太长,那么就需要优化优化了。录制结果的调用堆栈,横向表示时会出现带有更多详情的浮窗间,垂直方向表示调用栈,从上往下表示函数调用。滑动鼠标滚轮可以查看某段时间的调用栈信息。把鼠标放到Call Stacks调用栈的某个函数上面可以查看函数详细信息。这个一般是性能优化时关注,对于内存泄漏,主要用于帮助定位进行了什么操作。
  • Counter(计数器)窗格。在这里你可以看到内存使用情况(与Overview(概述)窗格中的HEAP(堆)曲线图相同),分别显示以下内容:JS heap(JS堆),documents(文档),DOM nodes(DOM节点),listeners(侦听器)和GPU memory(GPU内存)。勾选或取消勾选复选框可以将其从图表中显示或隐藏。

主要关注第三个的JS堆内存、节点数量、监听器数量。鼠标移到曲线上,可以在左下角显示具体数据。这些数据若有一个在持续上涨,没有下降趋势,都有可能是泄漏。

记得每次开始和结束录制前都点击垃圾回收。另外打开控制台会影响内存的回收,可以录制完后,重新打开不进行任何操作再次录制,与上次的录制进行比对。
上面提到任务管理器出现过“内存占用空间”一直增长,但是“Javascript占用的内存”增长缓慢或不增长的情况。可以关注下节点的数量,可以发现节点数量也一直在增长。

可能情况

闭包、意外的全局变量、定时器、dom对象和js对象的互相引用未置空等。

DOM泄漏

JS堆快照可以用来发现DOM泄露。在Class filter(类过滤器)文本框中输入Detached可以搜索分离的DOM树。如果分离节点被JS引用,有可能就是泄露点。

猜你喜欢

转载自blog.csdn.net/m0_38073011/article/details/98073667