返回

V8中垃圾回收工作的老司机之垃圾回收实现

前端

V8垃圾回收工作的老司机

在上篇中我们了解了V8垃圾回收工作的背景、设计目标、整体架构以及新生代收集算法的scavenge,在这里我们将详细介绍V8垃圾回收工作的老司机 ——老生代算法mark-sweep & mark-compact,以及新生代晋升老生代的机制,最后还会告诉你如何查看并扩充V8的内存。

一、老生代垃圾回收算法
因为新生代的对象生命周期较短,所以可以使用新生代垃圾回收算法scavenge

但由于老生代中的对象的存活时间比新生代的对象要长,很多对象会存活于多个垃圾回收周期,因此老生代使用了其他策略,包括mark-sweepmark-compact 两种算法。

  1. mark-sweep 算法
    通过对内存中的所有对象进行标记,然后清理掉所有未标记的对象。

  2. mark-compact 算法
    除了标记和清理之外,mark-compact 还会对内存中的对象进行整理。在 mark-compact 完成后,所有未被清理的对象都会被整理到内存空间的一块连续区域中,从而避免内存碎片。

由于mark-sweep 算法和 mark-compact 算法的实现复杂,且相关代码也比较多,因此本文不对其具体的实现进行剖析。

如果大家对具体的实现细节感兴趣,可以参考 V8 的官方文档。

二、新生代晋升老生代

新生代的晋升老生代机制,是指在scavenge之后,将新生代的幸存对象晋升到老生代,因为这些对象已经经过了新生代垃圾回收算法的考验,因此它们在老生代中存活下来的可能性会比较大。

三、如何查看并扩充 V8 内存

  1. 查看 V8 内存:

通过在 JavaScript 代码中使用 process.memoryUsage() 方法可以查看 V8 内存的使用情况。

const memoryUsage = process.memoryUsage();
console.log(memoryUsage);

输出结果:

{
  rss: 24716800,
  heapTotal: 1759232,
  heapUsed: 1154656,
  external: 142352
}
  • rss: 总内存使用量,包括 JavaScript 堆内存和 V8 内核内存。
  • heapTotal: 堆内存总量。
  • heapUsed: 堆内存已使用量。
  • external: 外部内存的使用量,包括 C++ 对象和 Node.js 模块。
  1. 扩充 V8 内存:

可以通过在启动 Node.js 时使用 --max-old-space-size--max-new-space-size 参数来扩充 V8 内存。

例如,以下命令将把老生代的最大内存设置为 4GB,新生代的最大内存设置为 1GB:

node --max-old-space-size=4096 --max-new-space-size=1024 app.js

以上内容仅为抛砖引玉,关于 scavengemark-sweepmark-compact、晋升老生代的垃圾回收过程的详细、如何查看并扩充 V8 内存等相关内容的进一步学习和理解,可以参考V8的官方文档。

希望能对你有所帮助,如果有什么问题,欢迎随时提出。