垃圾回收机制
垃圾回收机制
目的:清除不再使用的对象,腾出占用的内存空间
比如,当给一个变量重新赋值了一个新对象后,原来的对象就不再使用了
策略
引用计数法
- 当一个对象被引用时-引用次数 +1
- 当一个对象被取消引用时-引用次数 -1
- 引用数为 0 时-触发垃圾回收机制回收
缺陷:循环引用时-引用次数永远不可能为 0 ,无法回收,内存无法释放
循环引用: 当对象 OA 的属性 A 引用了 OA 对象本身,把变量重新赋值后,原来的 A 对象还是指向原来的 OA 内存空间,从而导致无法回收
标记清除法
关键点-标记、清除
- 首先将所有对象标记为 0 ,从根对象开始遍历,将存活的对象标记为 1
- 将标记为 0 的对象清除掉
- 最后将所有标记为 1 的对象重新标记为 0 ,方便下一次垃圾回收机制回收
问题: 对象内存空间位置是不连续的,如果进来一个新对象,找位置是个新问题
内存空间找位置
有三种方法分别是 First-fit、Best-fit、Worst-fit
- First-fit: 找到能放置下新对象的第一个块位置
- Best-fit: 找到能放置下新对象的最小的块
- Worst-fit: 找到最大的块,分一块空间给新对象
First-fit 性能最好
Worst-fit 会产生更多不连续的空间
V8 对垃圾回收机制的优化
优化标记算法
有些对象需要频繁回收,有些对象不需要频繁的回收
- 一般小的、新的、存活时间短的对象,需要频繁回收
- 大的、老的、存活时间长的对象不需要频繁回收
所以在内存堆中分出了两个区域,分别是新生代区域、老生代区域
- 新生代区域-小、新、存活时间段
- 老生代区域-大、老、存活时间长
新生代区域
内部有俩个空间,分别是 from 空间、to 空间
- from-使用空间
- to-闲置空间
- 当 from 空间要满的时候,开始标记,将存活的对象标记好
- 标记好后将他们复制到 to 空间中
- 最后再吧 from 空间清空,并且交换空间名称 to->from from->to
老生代区域
- 首先将所有对象标记为 0
- 将存活的对象标记为 1
- 将标记为 0 的对象全部清除
- 将标记为 1 的对象全部标记为 0
- 通过标记压缩算法整理内存空间位置
其他
执行机制
由于JS是单线程语言-执行垃圾回收机制时,JS 执行会被暂停(全停顿),V8 对这种情况做了一定的优化—垃圾回收机制支持多线程,并行回收
但依然可能出现阻塞 JS 执行的情况
于是就有了 增量标记
增量标记
特点:垃圾回收可以分段执行-JS和垃圾回收分段轮流交叉执行,最大化保证 JS 的执行
通过三色标记法来记录上一次执行的位置
三色标记法
作用: 将上次标记到的位置标记为灰色,当下次执行时从灰色标记位置开始重新标记
并发回收
JS 在主线程执行,垃圾回收在辅助线程执行
垃圾回收机制
http://blog.climbed.online/2023/11/24/Web -- Knowledge is infinite/前端/JavaScript/垃圾回收机制/