JavaScript内存泄漏

内存泄漏简介

内存泄漏(Memory Leak)是指程序中己动态分配的堆内存因为某种缘由程序未释放或没法释放,形成系统内存的浪费,致使程序运行速度减慢甚至系统崩溃等严重后果。程序员

内存泄漏缺陷具备隐蔽性、积累性的特征,比其余内存非法访问错误更难检测。由于内存泄漏的产生缘由是内存块未被释放,属于遗漏型缺陷而不是过错型缺陷。此外,内存泄漏一般不会直接产生可观察的错误症状,而是逐渐积累,下降系统总体性能,极端的状况下可能使系统崩溃。数组

垃圾回收机制

最常使用的方法叫作"引用计数"(reference counting):语言引擎有一张"引用表",保存了内存里面全部的资源(一般是各类值)的引用次数。若是一个值的引用次数是0,就表示这个值再也不用到了,所以能够将这块内存释放。浏览器

const arr = [1, 2, 3, 4];
console.log('hello world');

上面代码中,数组[1, 2, 3, 4]是一个值,会占用内存。变量arr是仅有的对这个值的引用,所以引用次数为1。尽管后面的代码没有用到arr,它仍是会持续占用内存。数据结构

let arr = [1, 2, 3, 4];
console.log('hello world');
arr = null;

上面代码中,arr重置为null,就解除了对[1, 2, 3, 4]的引用,引用次数变成了0,内存就能够释放出来了。ide

内存泄漏的识别方法

经验法则是,若是连续五次垃圾回收以后,内存占用一次比一次大,就有内存泄漏。这就要求实时查看内存占用。工具

浏览器识别

Chrome 浏览器查看内存占用,按照如下步骤操做。性能

alt text

alt text

  1. 打开开发者工具,选择 Timeline 面板
  2. 在顶部的Capture字段里面勾选 Memory
  3. 点击左上角的录制按钮。
  4. 在页面上进行各类操做,模拟用户的使用状况。
  5. 一段时间后,点击对话框的 stop 按钮,面板上就会显示这段时间的内存占用状况。

若是内存占用基本平稳,接近水平,就说明不存在内存泄漏。spa

命令行识别

命令行可使用 Node 提供的process.memoryUsage方法。命令行

console.log(process.memoryUsage());
// { rss: 27709440,
//  heapTotal: 5685248,
//  heapUsed: 3449392,
//  external: 8772 }

process.memoryUsage返回一个对象,包含了 Node 进程的内存占用信息。该对象包含四个字段,单位是字节,含义以下。code

alt text

  • rss(resident set size):全部内存占用,包括指令区和堆栈。
  • heapTotal:"堆"占用的内存,包括用到的和没用到的。
  • heapUsed:用到的堆的部分。
  • external: V8 引擎内部的 C++ 对象占用的内存。

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

WeakSet 和 WeakMap

前面说过,及时清除引用很是重要。可是,你不可能记得那么多,有时候一疏忽就忘了,因此才有那么多内存泄漏。

最好能有一种方法,在新建引用的时候就声明,哪些引用必须手动清除,哪些引用能够忽略不计,当其余引用消失之后,垃圾回收机制就能够释放内存。这样就能大大减轻程序员的负担,你只要清除主要引用就能够了。

ES6 考虑到了这一点,推出了两种新的数据结构:WeakSet 和 WeakMap。它们对于值的引用都是不计入垃圾回收机制的,因此名字里面才会有一个"Weak",表示这是弱引用。详细具体看阮一峰的ECMAScript 6 入门。

相关文章
相关标签/搜索