V8 内存管理和垃圾回收机制总结

这篇文章主要介绍 V8 的内存管理和垃圾回收知识。

V8 内存管理及垃圾回收机制浅析

由于 V8 引擎的原因,Node 在操作大内存对象时受到了一些限制,在 64 位的机器上,默认最大操作的对象大小约为 1.4G,在 32 位的机器上,默认最大操作的对象大小约为 0.7G。
如果我们的 Node 程序会经常操作一些大内存的对象,可以对这个默认值进行修改:

node --max-old-space-size=1700 index.js
node --max-new-space-size=1024 index.js

其中,max-old-space-size 表示设置老生代内存空间的最大容量,max-new-space-size 表示这只新生代内存空间的最大容量。但这两个值也是有上限的,不能无限设置,其中老生代内存空间最大的值约为 1.7G,新生代最大内存空间约为 1.0G。
至于新生代和老生代,这是 V8 对内存的一个分类,后文再介绍。
回到操作大内存对象的问题,如果 1.7G 的内存还是不够大怎么办呢?要知道 1.7G 是在 V8 引擎层面上做出的限制,要想避开这种限制,我们可以使用 Buffer 对象,Buffer 对象的内存分配在 C++ 层面进行,不受 V8 引擎限制。
注:通过 process.memoryUsage() 方法可以用来查看 V8 引擎的内存使用量,通过 os.totalmem() 方法和 os.freemem() 方法分别可以查看操作系统的总内存和空闲内存。

// 查看 V8 的内存使用情况
process.memoryUsage()
{ 
  rss: 31469568,
  heapTotal: 7708672,
  heapUsed: 5152856,
  external: 8609 
}

// 查看操作系统总内存
os.totalmem()
8279511040
// 查看操作系统的空闲内存
os.freemem()
1610977280

通过上面几个方法获取到的内存都是以字节为单位。

新生代和老生代

V8 将内存分为两类:新生代内存空间和老生代内存空间,新生代内存空间主要用来存放存活时间较短的对象,老生代内存空间主要用来存放存活时间较长的对象。对于垃圾回收,新生代和老生代有各自不同的策略,下面依次进行介绍。

新生代垃圾回收

新生代内存中的垃圾回收主要通过 Scavenge 算法进行,具体实现时主要采用了 Cheney 算法。Cheney 将内存空间一分为二,每部分都叫做一个 Semispace,这两个 Semispace 一个处于使用,一个处于闲置。处于使用中的 Semispace 也叫作 From,处于闲置中的 Semispace 也叫作 To。
在垃圾回收运行时时,会检查 From 中的对象,当某个对象需要被回收时,将其留在 From 空间,剩下的对象移动到 To 空间,然后进行反转,将 From 空间和 To 空间互换。进行垃圾回收时,会将 To 空间的内存进行释放,如下图所示:


新生代垃圾回收.png

简而言之,就是 From 空间中存放不需要被回收的对象,To 空间中存放需要被回收的对象,当垃圾回收运行时,将 To 空间中的对象全部进行回收。

新生代对象的晋升

前面说过,新生代内存空间用来存放存活时间较短的对象,老生代内存空间用来存放存活时间较长的对象。新生代中的对象可以晋升到老生代中,具体有两种方式:

  1. 在垃圾回收的过程中,如果发现某个对象之前被清理过,那么会将其晋升到老生代内存空间中
  2. 在 From 空间和 To 空间进行反转的过程中,如果 To 空间中的使用量已经超过了 25%,那么就将 From 中的对象直接晋升到老生代内存空间中

老生代垃圾回收

说完新生代的垃圾回收,再来看下老生代中的垃圾回收。首先,老生代内存空间和新生代内存空间的结构不一样,其是一个连续的结构,而不像新生代内存空间那样分为 From 和 To 两个部分:


老生代内存空间.png

老生代内存空间中的垃圾回收有标记清除(Mark Sweep)和标记合并(Mark Compact)两种方式。

Mark Sweep

Mark Sweep 是将需要被回收的对象进行标记,在垃圾回收运行时直接释放相应的地址空间,如下图所示(红色的内存区域表示需要被回收的区域):


标记清除.png

如上图所示,使用 Mark Sweep 进行垃圾回收会产生一个问题,就是垃圾回收后内存会出现不连续的情况,为了解决这个问题,出现了 Mark Compact 方案。

Mark Compact

Mark Compact 的思想有点像新生代垃圾回收时采取的 Cheney 算法:将存活的对象移动到一边,将需要被回收的对象移动到另一边,然后对需要被回收的对象区域进行整体的垃圾回收。


标记合并.png

上图展示了在老生代内存空间使用 Mark Compact 进行垃圾回收的过程。

总结

本文主要简单介绍了 Node 的内存管理和垃圾回收相关的知识:

  • V8 的大对象操作限制问题和解决方案
  • 获取内存使用量的几个方法
  • 新生代和老生代的概念
  • 新生代和老生代的垃圾回收方案

附:参考资料
V8的垃圾回收机制与内存限制
node 内存限制的问题
node内存控制

完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267