栈的内存空间是主动调配的,它由零碎主动开释,堆的内存空间是动态分配的,大小不定,不会主动开释,须要 JS 引擎开释这些内存。v8 采纳的分代式垃圾回收机制。
分代式垃圾回收机制
v8 堆内存构造蕴含新生代内存区,老生代内存区,大对象区,Map 区,代码区。垃圾回收产生在新生代内存区和老生代内存区。
从根(window,global)开始,找所有从根开始援用的对象,而后找这些对象援用的对象……,始终递归,被找到的对象就是流动对象,从根往下找不到的对象就是未流动对象,能够被回收。
新生代
存储空间小,垃圾回收频繁
- 新生代空间分为半个 From 空间,半个 To 空间
- 申明的对象首先调配到 From 空间。
- 垃圾回收时,复制 From 空间的流动对象到 To 空间。留在 From 空间的非流动对象会被主动回收
- 复制实现后,From 空间和 To 空间实现调换。To 空间变成新的 From 空间,From 空间变成新的 To 空间。
老生代
存储空间大,寄存存活工夫较久的对象
- 新生代的对象通过屡次复制后仍旧存活(至多经验过一次复制,且新生代 To 空间的内存占比超过了 25%),在下一次进行垃圾回收时,该对象间接转移到老生代中。
- 遍历堆中所有的对象,标记流动对象,革除未流动对象。
- 对象革除后,在整顿的过程中,会将流动的对象往堆内存的一端进行挪动。(碎片整顿,不便寄存较大的对象)
- 能够标记或者整顿一部分对象,而后暂停,将执行权交给 js 主线程,待主线程闲暇时再从原来标记的中央持续标记或者整顿。(不影响主线程运行)
- 也能够利用增量标记、懒性清理、并发、并行来缩小主线程挂起的工夫。