Amybiubiu / Blog

6 stars 0 forks source link

v8垃圾收集 #4

Open Amybiubiu opened 3 years ago

Amybiubiu commented 3 years ago

感觉这个东西有些废图,但我又懒得搞图。

之所以想看v8垃圾收集机制,是因为在看闭包时产生的困惑,关于它如何做到销毁函数部分的的时候,还保留闭包。

首先,JS 有八种数据类型,除 Object 外为引用类型外,其它成为原始类型。原始类型的变量存储在 Stack 内,引用类型的变量的值存储在 Heap 内,此外对于 JS 引擎识别出的 Closure (并且在调试面板上也可以查看到 Closure 内的实际存储内容)的存储也是在 Heap。原始类型变量互相赋值时,是“按值传递”,引用类型互相赋值时,是”按地址传递“。

Stack 空间的回收,是通过 ESP (记录当前执行状态的指针)的移动来实现的,不涉及到垃圾回收器。Heap 空间的回收依靠垃圾回收器进行。

V8 会把堆空间分为新生代和老生代两个区域(名字怪奇怪的,还不如叫短时使用区域和长时使用区域呃呃),并且老生代分配的空间比新生代大很多(2 8 法则)。V8 分别使用两个不同的垃圾回收器,以便更高效地实施垃圾回收。副垃圾回收器,主要负责新生代的垃圾回收。主垃圾回收器,主要负责老生代的垃圾回收。

垃圾回收器共同的执行流程:

副垃圾回收器: 新生代中用 Scavenge 算法来处理。所谓 Scavenge 算法,是把新生代空间对半划分为两个区域,一半是对象区域,一半是空闲区域,新加入的对象都会存放到对象区域,当对象区域快被写满时,就需要执行一次垃圾清理操作。在垃圾回收过程中,首先要对对象区域中的垃圾做标记;标记完成之后,就进入垃圾清理阶段,副垃圾回收器会把这些存活的对象复制到空闲区域中(互换),同时它还会把这些对象有序地排列起来,所以这个复制过程,也就相当于完成了内存整理操作,复制后空闲区域就没有内存碎片了。经过两次垃圾回收依然还存活的对象,会被移动到老生区中。

主垃圾回收器: image

全停顿: 由于进行垃圾回收的过程,JS要暂停执行,为避免明显的卡顿,将垃圾回收过程分割成若干片段,穿插标记(非)活动对象。称为增量标记(Incremental Marking)算法。

Amybiubiu commented 3 years ago

看这个时顺带看到的东西

Amybiubiu commented 3 years ago

此内容为极课时间【浏览器工作原理与实践】的总结,并非原创。

Amybiubiu commented 3 years ago

原始类型的变量存储在 Stack 内,引用类型的变量的值存储在 Heap 内。这部分内容有误。有人在浏览器看过不符合这个分配规律的情况,具体的忘记了,之后再补 2333