# JS垃圾回收机制
垃圾回收是靠平台实现的,如:JVM,V8。所以c++和c就没有垃圾回收机制。
会讲述以下内容
- 垃圾回收概念
- V8引擎的垃圾回收过程
- 各种垃圾回收算法
- 内存泄露
# 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%
- 新生代复制时,已经历过复制算法的可达对象
- 大对象(具体多大?反正我不知道)
老生代 -> 三种算法
- 标记清除
- 由于老生代大部分对象是存活的,所以采用:存活对象标记,未标记对象清除
- 标记整理 / 压缩算法
- 由于标记清除会产生大量的内存碎片,内存碎片不一定能容纳大对象。所以需要标记整理
- 标记整理方法是:将所有存活对象往一端移动
- 增量标记
- 将标记阶段分为若干小步骤,解决垃圾回收时可能的卡顿问题
# WeakSet 和 WeakMap
弱引用:对于值的引用都是不计入垃圾回收机制
见 http://www.ruanyifeng.com/blog/2017/04/memory-leak.html
# 内存泄露
内存泄露就是垃圾未被回收
如:古老的引用计数算法,在处理循环引用是会出现内存泄露
内存泄露的查询
Chrome浏览器 -> Performance 勾选 Memory -> 录制 -> 会展示Heap占用情况