返回

Chrome、Node.js幕后英雄V8引擎的垃圾回收(上)

前端

V8引擎是时下炙手可热的JavaScript引擎,它的足迹不仅遍布Chrome,Node.js等浏览器领域,也逐步在Deno等新贵中占据着一席之地。

国庆假期,身处厦门的笔者积极响应防疫政策,遂在家中潜心学习。在此期间,笔者新习得了关于V8引擎垃圾回收机制的知识,现分享给大家。

该机制分为两部分,本篇主要介绍V8的内存分配、大小及新生代垃圾回收算法“scavenge”。

对于从事前端开发、Node.js开发的朋友,相信V8并不陌生。但对于其运作原理,可能还有很多未知之处。这篇文章将带你深入了解V8引擎的内部构造。

那么话不多说,让我们从一个关键问题开始:V8引擎是如何管理内存的?

V8的内存分配

V8引擎采用分代垃圾回收算法,将内存分为新生代和老年代。

新生代存储着最近分配的对象,由于这些对象存活时间较短,因此垃圾回收频率较高。老年代存储着存活时间较长的对象,其垃圾回收频率较低。

V8引擎在新生代中使用“scavenge”算法进行垃圾回收。该算法将新生代内存划分为两个半空间:From Space和To Space。

From Space用于存储活动对象,而To Space则为空闲。当From Space空间不足时,会触发一次scavenge。

V8新生代大小

V8引擎会根据程序的内存使用情况动态调整新生代的大小。

新生代大小的初始值为2MB,最大值为8MB。当新生代中活动对象所占的内存超过新生代总内存的25%时,V8引擎会将新生代大小增加一倍。

当新生代中活动对象所占的内存低于新生代总内存的12.5%时,V8引擎会将新生代大小减半。

scavenge算法

scavenge算法的原理是将From Space中的活动对象复制到To Space中,然后将From Space中的所有对象标记为可回收。

具体步骤如下:

  1. 将From Space中的所有指针指向To Space中的对应对象。
  2. 遍历From Space,将所有对象标记为可回收。
  3. 将To Space和From Space交换,使To Space成为新的From Space,From Space成为新的To Space。

scavenge算法的优点是速度快,因为只需要复制活动对象,而不需要遍历所有对象。

但scavenge算法的缺点是会产生内存碎片。为了解决这个问题,V8引擎会在新生代中使用“mark-sweep”算法进行压缩。

mark-sweep算法的原理是首先标记所有活动对象,然后释放未标记的对象所占用的内存。

mark-sweep算法的优点是不会产生内存碎片,但其速度较慢。

V8引擎会根据新生代中活动对象的分布情况,选择使用scavenge算法还是mark-sweep算法进行垃圾回收。

文章到此结束,下篇将介绍V8引擎的老年代垃圾回收算法“mark-sweep-compact”。

保持关注,下篇见!