node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,这是来自 Node.js 官网的一句话。所以 Node.js 中的 GC 就是 V8 引擎的 GC
在 Node.js 环境里提供了 process.memoryUsage 方法用来查看当前进程中内存使用的情况,单位为字节
- rss(resident set size):RAM 中保存的进程占用的内存部分,包括代码本身、栈、堆。
- heapTotal:堆中总共申请到的内存量
- heapUsed: 堆中目前用到的内存量,判断内存泄漏我们主要以这个字段位置
- external:V8 引擎内部的 C++ 对象占用的内容
在 V8 机制中,64 位的机器大约为 1.4GB,32 位机器大约为 0.7GB
--max-old-space-size=2048
--max-new-space-size=2048
采用 Scavenge 算法,由 C.J.Cheney 在 1970 年在论文中提出,Scavenge 算法非常快适合少量内存的垃圾回收 新生代空间会被一分为二划分为两个相等大小的 from-space 和 to-space。它的工作方式是将 from-space 中存活的对象复制过来,然后移动他们到 to space 中或者被提升到老生代空间中,对于 from space 中没有存活的对象将会被释放。完成这些复制后在将 from space 和 to space 进行互换
新生代空间在垃圾回收满足一定条件(是否经历过 Scavenge 回收、to space 的内存占比)会被晋升到老生代空间中,在老生代空间中的对象都已经至少经历过一次或者多次的回收所以它们的存活概率会更大。在使用 Scavenge 算法则会有两大缺点一是将会重复的复制存活对象使得效率低下,二是对于空间资源的浪费,所以在老生代空间中采用了 Mark-Sweep(标记清除) 和 Mark-Compact(标记整理) 算法
- Mark-Sweep 处理时分为标记、清除两个步骤,与 Scavenge 算法只复制活对象相反的是在老生代空间中由于活对象占多数 Mark-Sweep 在标记阶段遍历堆中的所有对象仅标记活对象把未标记的死对象清除,这时一次标记清除就已经完成了
- 看似一切 perfect 但是还遗留一个问题,被清除的对象遍布于各内存地址,产生很多内存碎片。
- 在老生代空间中为了解决 Mark-Sweep 算法的内存碎片问题,引入了 Mark-Compact(标记整理算法),其在工作过程中将活着的对象往一端移动,这时内存空间是紧凑的,移动完成之后,直接清理边界之外的内存。