v8 所使用的垃圾回收算法是分代垃圾回收。分为新生代和老生代,新生代用于存储生命周期较短的对象,回收频率频繁。老生代对象的生命周期较长,回收成本高。
v8 会将新生代内存分为两个部分,分别是 from 和 to,内存各占一半,在开始回收的时候,对from 部分使用可达性分析,也可以理解为标记清除算法的标记部分,从根对象出发,把能够访问到的对象移动到 to 里面,移动完成之后,将 from 和 to 进行互换,再进行下一轮的回收。如果有对象经历了两次新生代垃圾回收还没有被回收,要将其移动到老生代内存空间当中。
在老生代内存中,采用的是标记清除算法,从根节出发,找到能够到达的对象,然后将不可达的对象进行清除。清除完成之后,会存在大量的内存碎片,这时候采取的策略为标记压缩策略,将活跃的对象移动到内存的另一端,紧密连接,这样就能将内存碎片进行消除。
新生代和老生代的内存大小一般相差 2-3 个数量级,具体的内存大小根据运行环境不同改变,也可以手动调整内存大小。新生代内存桌面端一般为 16MB ,from 和 to 各占 8MB,移动端为 1-2MB ,老生代内存在桌面端为 700MB-1.4GB。
由于 js 的单线程机制,垃圾回收的线程执行过长就会造成页面卡顿。v8 通过增量垃圾回收和并发垃圾回收的方式将垃圾回收分为多个小步骤,或者采用并发的方式,避免长时间的暂停。