谈及 Node,不得不谈它高明的内存控制。
Node 的创始人 Ryan Dahl 很明智地选择了 google chrome 的成功之源,即性能卓越的 V8 引擎(事件驱动、非阻塞I/O)来作为 JavaScript 作为运行时虚拟机。
因为不论浏览器还是 Node,都是基于 V8 引擎的,而 JavaScript 对象所占内存都是通过 V8 来进行分配和管理的,因此只要基于 V8,不论是浏览器还是 Node,都使用同样的内存管理机制。
对前端 web 页面来说,64 位的机器可以使用约 1.4 GB 的内存,这已经够用了。而对于更大内存的对象,V8 无法直接处理,这就是 Node 需要解决的问题。
一般对象都存放在堆内存中,而基本数据类型存放在栈内存中。
为什么 V8 不充分使用内存空间,而只使用有限内存呢?
这是因为受到 V8 的垃圾回收机制所限。
在垃圾回收过程中,会导致 JavaScript 线程的暂停执行。一次非增量式的垃圾回收甚至要一秒以上。
为了满足响应用户和提高性能,V8 选择直接限制堆内存大小。
V8 的回收策略为分代式垃圾回收机制。
顾名思义,分代式回收会将堆内存分为新生代和老生代,前者存放存活时间较短的对象,后者则存放存活时间较长的对象。
在 64 位系统中,新生代大小为 32 MB,而老生代大小为 1464 MB。
对于新生代中的对象,有不少转瞬即逝的对象,使用 Scavenge 算法进行垃圾回收。
Scavenge 算法: 复制存活的对象。将对象从 From 空间移动到 To 空间保留下来,来回往复。
通常新生代内存中的对象经过 Scavenge 算法回收,能够通过晋升进入到老生代。
而老生代中的对象通常都存活较久,则使用 Mark-Sweep(主要) 和 Mark-Compact(内存不足时,对晋升的对象使用) 算法进行垃圾回收。
Mark-Sweep 算法: 标记清除死亡对象。将没有使用的对象标记为死亡,并在垃圾回收中进行清除。 Mark-Compact 算法:标记清除死亡对象,并将存活对象移动到一端(不会产生内存碎片)。