Node 是如何做 GC (垃圾回收)的?下面本篇文章就来带大家了解一下。
node.js极速入门课程:进入学习
GC,Garbage Collection,垃圾回收。在编程中,一般指的是内存自动回收机制,会定时将不需要用到的数据进行清除。
Node.js 底层使用了 V8 引擎。V8 是 Google 开源的一款高性能 JavaScript 引擎,使用了 C++ 进行编写。【相关教程推荐:nodejs视频教程】
Node.js 的内存主要分成三部分:
-
代码空间:存放代码段的地方;
-
栈:函数调用栈产生的临时变量,为一些基本类型,比如数字、字符串、布尔值,以及对象引用(保存的是地址,不保存对象本身)。
-
堆:存放对象等数据;
堆内存
Node.js 底层使用的是 V8,下面讲解一下 V8 的内存回收机制。
首先 JS 中所有的对象都会保存在堆内存中。在创建进程的时候,会分配一个初始大小的堆内存,然后我们的对象就会放到里面。
当对象越来越多,堆内存会不够用,此时堆内存会动态地扩大。如果到达一个最大限制(现在通常是 4GB),就会堆内存溢出的错误,然后终止 Node.js 进程。
新生代与老生代
V8 首先将内存分成两部分,或者说两个生代(generation):
-
新生代(yong generation):保存一些存活时间较短的对象;
-
老生代(old generation):保存存活时间长或者长驻的对象。
新生代很小,这里会存放一些存活时间很短的对象,通常它们会被频繁地回收(比如函数的调用栈的一些临时对象)。
新生代可通过
node --max-semi-space-size=SIZE index.js
修改新生代的大小,单位为 MB。另外,老生代则通过
--max-old-space-size=SIZE
来设置
新生代的 Scavenge 算法
新生代使用了 Scavenge 算法,是一种基于 copy(复制)的算法。
新生代会分成两个空间,这种空间称为 semispace,它们为:
-
From 空间:新声明的对象会放入这里
-
To 空间:用作搬移的空间
新声明的对象会放入到 From 空间中,From 空间的对象紧密排布,通过指针,上一对象紧贴下一个对象,是内存连续的,不用担心内存碎片的问题。
所谓内存碎片,指的是空间分配不均匀,产生大量小的连续空间,无法放入一个大对象。
当 From 空间快满了,我们就会遍历找出活跃对象,将它们 copy 到 To 空间。此时 From 空间其实就空了,然后我们将 From 和 To 互换身份。
如果一些对象被 copy 了多次,会被认为存活时间较长,将被移动到老生代中。
这种基于 copy 的算法,优点是可以很好地处理内存碎片的问题,缺点是会浪费一些空间作为搬移的空间位置,此外因为拷贝比较耗费时间,所以不适合分配太大的内存空间,