[Node] 内存溢出与 old-space 大小调整

如题所述

第1个回答  2022-07-16

V8 为 Node.js 应用,默认只会分配了大概 1400 MB(仅本地测试的结果) 的内存空间。
超出了这个限额,就会内存溢出。

我们来写一段程序,制造一个内存溢出错误,

执行一下,

可以看到当内存占用达到 1400 MB 时,就报错了,

V8 使用了分代垃圾回收机制,将堆(heap)划分成了几个不同的空间。

参考一篇比较老的文章, A tour of V8: Garbage Collection #Heap organization

文中提到了 new-space 和 old-space,

大致含义是,新对象一般会先分配到 new-space 中(只有 1 - 8 M 大小),
new-space 满了以后会触发一次小型的(minor)垃圾回收,
如果对象经历了两次小型(minor)垃圾回收还活着,就会被移到 old-space 中(这个空间比较大)。
old-space 满了会经历一次大型(major)垃圾回收(采用标记-清除回收算法)。

所以,如果我们一直分配新对象且不释放它,就会最终被放到 old-space 中。
一旦 old-space 占用率超出限额,就会造成内存溢出。

注:
V8 的垃圾回收机制也是与时俱进的,
最近的一些进展,可参考 Trash talk: the Orinoco garbage collector ,
上面介绍的内容大同小异。

有以下两种方式,可以调整 old-space 大小,
在某些情况下,或许能暂时避免 Node.js 内存溢出。

我们来看看效果,

我们看到产生内存溢出时,内存占用情况不同了,

A tour of V8: Garbage Collection
Trash talk: the Orinoco garbage collector
Node.js - Command line options: --max-old-space-size=SIZE
Node.js - Command line options: NODE_OPTIONS=options...