Node.js中的 GC 「垃圾回收」机制

1. 什么是 GC「垃圾回收」机制

GC(Garbage Collection,垃圾回收)是指在编程语言中,对于无用的内存空间进行自动回收和释放,减少程序员手动操作的时间和难度,以及减轻内存管理带来的负担。Node.js是基于V8引擎的JavaScript运行环境,在V8的垃圾回收机制上对其进行了改进优化。Node.js中的垃圾回收器主要工作是在代码运行时,不断扫描内存,释放不再使用的内存空间。

2. Node.js中的垃圾回收器分类

2.1 新生代垃圾回收器

新生代垃圾回收器主要处理存活时间短、占用空间小的对象。Node.js中采用的是V8中的Scavenge垃圾回收器。这个回收器是将内存一分为二,每一部分称为semispace。有一个部分用于存储新产生的对象(From空间),当From空间被使用满后,会将其中还存活的对象复制到另一部分中(To空间),然后清空From空间,这样保证了To空间始终是空闲的。在复制对象到To空间的过程中,如果对象存活时间较长,则会被放入老生代空间中,否则继续放入From空间中。

// 示例代码:对象会被先创建在From空间,然后通过复制到To空间进行清理

let obj1 = {}

let obj2 = {}

let obj3 = {}

2.2 老生代垃圾回收器

老生代垃圾回收器处理存活时间长、占用空间大的对象,老生代空间一般比较稳定,当从新生代空间晋升过来的对象到达一定数量或者老生代空间使用达到一定阈值时,老生代垃圾回收器会开始工作。Node.js中采用的是V8中的Mark-Sweep和Mark-Compact两种垃圾回收器。Mark-Sweep垃圾回收器会标记所有存活的对象,然后清除未标记的对象,此时会产生大量的碎片。Mark-Compact则会在清除未标记对象的同时,将存活的对象移到内存空间的一端,然后清除边界外的所有内存。

// 示例代码:对象在新生代空间产生并晋升到老生代空间

function foo() {

let obj1 = {}

let obj2 = {}

let obj3 = {}

// ...

}

for (let i = 0; i < 10; i++) {

foo()

}

3. 垃圾回收器的执行流程

垃圾回收器的执行流程一般包括以下步骤:

3.1 标记阶段

对于老生代空间中的对象,先找到所有的根(即全局变量、堆栈中的变量等),从根开始遍历所有的对象,标记这些对象为活动对象。活动对象是指有引用关系的对象,它们在运行过程中会被使用到。

3.2 对象清除/移动阶段

清除或移动标记为未活动的对象。在新生代垃圾回收器中,清除之后的内存空间会保留,等待下次GC时再被复用。在老生代垃圾回收器中,为了避免产生碎片,会将存活的对象紧凑放置,放置在一起的内存空间被释放出来,可以再次被使用。

3.3 内存整理阶段

为了避免产生内存碎片,老生代垃圾回收器在对象清除/移动阶段之后,还需要再进行一次整理内存空间的操作。

4. 如何避免垃圾回收带来的性能问题

虽然垃圾回收帮助减轻了内存管理的工作,但是会对程序运行的性能产生影响。因此,我们需要尽量减少多次创建和销毁对象的操作,以及减少在全局区域定义不必要的变量。在代码中使用函数封装、对象池技术、复用已有的对象等方法,都可以有效减小垃圾回收的压力。

5. 总结

Node.js中的垃圾回收机制,主要包括新生代垃圾回收器和老生代垃圾回收器,分别处理无用的内存空间。垃圾回收器的执行流程一般包括标记阶段、清除/移动阶段和内存整理阶段。为了避免垃圾回收带来的性能问题,我们可以使用封装、对象池技术和复用已有对象等方法。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。