前言
javascript中的内存管理是自动执行的。那么这些基本类型、对象、函数所占用的内存是如何被释放的呢?我们以v8引擎的垃圾回收机制来解释这个过程。
内存查看
如果我们想查看当前程序的内存使用情况,我们可以通过process.memoryUsage()来查看。
console.log(process.memoryUsage());
// 输出结果
{
rss: 19570688,
heapTotal: 6537216,
heapUsed: 3945144,
external: 8272
}
heapTotal是总共分配的堆内存;heapUsed是当前使用的堆内存。
堆内存分代
在v8引擎中,堆内存分为两个部分:新生代内存空间和老生代内存空间。其中新生代内存空间又分为from区和to区,这两个区大小一样。
- 新生代内存
- from区
- to区
- 老生代内存
垃圾回收机制
新生代回收机制
新创建的内存都是在from区,隔一段时间垃圾回收机制启动,把当前有引用的对象复制到to区,没有引用的就会被清除。此时,to区和from区互相转换(原来的to区变成新的from区,原来的from区变成新的to区)。如果一个对象在from区和to区移动次数达到5次就会被移动到老生代内存空间(说明它长时间都会存在当前环境中)
老生代回收机制
老生代回收机制采用的是标记清除算法(Mark Sweep),先将存活的对象进行标记,清除时只清除没有标记的(老生代中都是生命周期长的对象,刚好死亡的对象少),不过此时会出现内存不连续的情况,如果此时需要放一个大对象,则放不下,从而导致再次引起回收。然而这次回收是不必要的。因此又产生了标记整理算法(Mark Compact)。先将死亡的对象进行标记,然后将存活得对象往一段移动,移动完成后,清理掉边界外的内存。