学习 Node.js 内存管理和垃圾回收机制

本文详细介绍了JavaScript引擎V8的内存管理,包括内存限制、内存指标的查看,以及V8的垃圾回收机制,如Scavenge算法和Mark-Sweep/Mark-Compact算法。此外,还探讨了内存泄漏的原因、分类,如缓存、模块加载和事件监听,提供了内存泄露排查工具如node-heapdump和v8-analytics,并分享了内存泄漏的解决方案。
摘要由CSDN通过智能技术生成

JavaScript 的标准 ECMAScript 里没有对 GC 做相关的要求,因此 JavaScript 的 GC 机制完全由引擎决定:

一般存在三种垃圾回收的方法:

  • stop-the-world: 它指的是在执行垃圾回收的过程中,会暂停程序的执行
  • 增量式 GC(incremental),即程序不需要等到垃圾回收完全结束才能重新开始,在垃圾回收的过程中控制权可以根据情况临时交给程序执行
  • 并发式 GC(concurrent),即在垃圾回收的同时不需要停止程序的运行,两者可以同时进行,只有在个别时候需要短暂停下来让垃圾回收器做一些特殊的操作
V8 内存管理
  • 内存限制

受垃圾回收机制的限制(耗时长),V8的内存限制(64系统下为1.4GB,32系统下为0.7GB),注意的是Buffer存储在堆外存中,会不受v8内存分配的限制。在启动app时可以通过传递参数控制内存的大小:

node --max-old-space-size=1700 test.js  // 单位为MB,设置老生代存储空间的大小 
node --max-new-space-size=1024 test.js  // 单位为KB,设置新生代存储空间的大小
  • 内存指标

Node.js 提供了 process.memoryUsage/os.totalmem/os.freemem 函数来查看内存指标

process.memoryUsage()
=> {
    
  rss: 22749184,  // 常驻内存集的大小,就是给该进程分配了多少物理空间,包括堆,栈,代码段
  heapTotal: 7708672, //分配的堆内存大小
  heapUsed: 5078856,  //堆已经使用的内存大小,内存泄漏主要查看该指标
  external: 8614     // V8 引擎内部的 C++ 对象占用的内存
}

//返回操作系统的总内存大小
os.totalmem()
=> 17179869184

//返回操作系统的闲置内存大小
os.freemem()
=> 5585453056
V8的垃圾回收机制
v8垃圾回收算法:

V8 内存分为新生代区和老生代区,一般刚刚新建的对象都存放在新生代区,然后存活周期比较长的对象就会被放入老生代区,新生代区和老生代区都有各自的垃圾回收算法:

  • Scavenge算法(新生代区):

采用复制的方式,将堆内存一分为二,通过将存活的对象在两个块内存之间复制实现,复制后重新整理内存,删除碎片。特点是由于生命周期短的对象只占少部分,时间效率比较高,但是由于只能使用堆内存一半的空间,空间利用率不高,适用于新生代对象;

  • 对象晋升:

在一定的条件下需要将新生代中存活周期长的对象复制到老生代中,完成对象晋升,对象晋升的条件有两个:

- 对象是否经过多次Scavenge回收
- 新生代空间的内存占用比超过限制
  • Mark-Sweep和Mark-Compact算法(老生代区):

老生代重要采用Mark-Sweep和Mark-Compact相结合进行垃圾回收:

- Mark-Sweep 先标记死的对象,然后清除死的对象,会产生碎片。
- Mark-Compact 会在标记死亡对象后,对内存进行整理,无内存碎片产生,速度相对比较慢

V8 的老生代区主要使用 Mark-Sweep,在空间不足的情况下才使用 Mark-Compact 算法。并且使用增量标记回收(Incremental Marking):由于老生代一次完全的垃圾回收耗时长,如果完全停顿下来进行垃圾回收,回收完以后再执行应用逻辑,性能会很差,所以采用 Incremental Marking 方式进行回收,采用增量标记,每做完一个步进,执行一会应用逻辑,提高性能;

查看垃圾回收日志:
  • –trace_gc参数:启动时添加该参数,可以查看 node 日志回收信息:
node --trace_gc app.js
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值