# JS垃圾回收机制

垃圾回收是靠平台实现的,如:JVM,V8。所以c++和c就没有垃圾回收机制。

会讲述以下内容

  1. 垃圾回收概念
  2. V8引擎的垃圾回收过程
  3. 各种垃圾回收算法
  4. 内存泄露

# JS 垃圾回收

首先涉及2个概念:栈和堆。

  • 栈(stack)
    • 存放原始值,引用
    • 后进后出
    • 连续的储存空间,空间小,读写快
  • 堆(heap)
    • 存放引用的值
    • 先进先出
    • 散列的储存空间,空间大,读写慢

题外话:JS的.unshift()会比.pop()要慢,见(JS语言精粹)

堆的内存由特定的垃圾回收算法进行。

可达性算法

判断堆内存是否存活的方法

通过一系列的GC Roots的对象作为起始点,从这些根节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

# V8引擎 的垃圾回收过程

首先采用分代算法将堆中对象分为2类:新生代 和 老生代

新生代

新生代中存放新的对象。可用空间为老生代的1/40。

新生代使用复制收集算法

  • 分割新生代空间(二等分)
    • 使用中的空间称为From,闲置的空间为To。
  • 可达对象会被复制到To空间或晋升老生代
  • 对象复制完毕 From空间会被清理,然后和To空间将进行角色反转

老生代

老生代存放的都是老油条哦

进入老生代的规则

  • 新生代复制时,To空间已使用25%
  • 新生代复制时,已经历过复制算法的可达对象
  • 大对象(具体多大?反正我不知道)

老生代 -> 三种算法

  1. 标记清除
    • 由于老生代大部分对象是存活的,所以采用:存活对象标记,未标记对象清除
  2. 标记整理 / 压缩算法
    • 由于标记清除会产生大量的内存碎片,内存碎片不一定能容纳大对象。所以需要标记整理
    • 标记整理方法是:将所有存活对象往一端移动
  3. 增量标记
    • 将标记阶段分为若干小步骤,解决垃圾回收时可能的卡顿问题

# WeakSet 和 WeakMap

弱引用:对于值的引用都是不计入垃圾回收机制

见 http://www.ruanyifeng.com/blog/2017/04/memory-leak.html

# 内存泄露

内存泄露就是垃圾未被回收

如:古老的引用计数算法,在处理循环引用是会出现内存泄露

内存泄露的查询

Chrome浏览器 -> Performance 勾选 Memory -> 录制 -> 会展示Heap占用情况

豫ICP备19025630号