浅谈Node的内存泄露问题


Posted in NodeJs onMay 06, 2022

1、node内存相关知识

无论是运行在浏览器端的js,还是运行在node中的js,关于内存管理的方案,都是通过垃圾回收机制来实现内存的分配和释放。当我们的代码编写有缺陷时,可能就无法通过gc来释放内存,这个时候,我们就造成了内存泄露。

  • Node.js进程的内存管理,都是由 V8 引擎自动处理的,包括内存的分配和释放。V8 自动处理内存的分配和释放,叫垃圾回收机制(gc)。

  • 垃圾回收机制,解决了大部分内存管理的问题,但是并不意味着内存泄露的问题就不存在。在一些特殊的场景下,会发生内存泄露。

  • 垃圾回收机制,是根据root对象(window/global)依次梳理对象的引用,如果能从root的引用链到达访问,V8就会将其标记为可到达对象,反之为不可到达对象。被标记为不可到达对象(即无引用的对象)后就会被 V8 回收。

2、哪些情况会造成内存泄露

第一、全局变量

全局变量会直接挂在root对象上,不会被清除掉。只要一个变量挂载到root对象上,自程序运行起,它就会一直占据着内存空间。

第二、函数闭包

闭包会引用父级函数的变量,如果闭包未释放,就会导致内存被持续占用,从而导致内存泄露。

在实际的业务场景中,引用的变量极有可能是挂载到从root可以追溯到的对象上,导致的内存泄露。

第三、事件监听

多次的重复的事件监听,可以导致内存泄露的问题。

3、内存泄露的监测

node的内存泄露监测,基本原理如下,

在node中,有专门进行内存监测的工具——heapdump。

heapdump,是一个npm包,使用比较简洁的语法,就能生成内存快照文件。

内存快照文件,是以heapsnapshot为扩展名的一种文件,该文件记录了关于内存使用的基本情况。

Chrome devTools作为一种工具,可以对内存快照文件,进行分析。

一段监测内存变化的代码如下:

const EventEmitter = require('events');
const heapdump = require('heapdump');
global.test = new EventEmitter();
heapdump.writeSnapshot('./' + Date.now() + '.heapsnapshot');
function run3() {
  const innerData = new Buffer(100);
  const outClosure3 = function () {
    void innerData;
  };
  test.on('error', () => {
    console.log('error');
  });
  outClosure3();
}
for(let i = 0; i < 100; i++) {
  run3();
}
// run3();
// gc();
heapdump.writeSnapshot('./' + Date.now() + '.heapsnapshot');

其中,heapdump.writeSnapshot方法,就是生成内存快照文件的方法。

我们使用node的方式,进行执行,就会生成两个heapsnapshot文件。

4、Chrome DevTools进行分析和对比

在Chrome DevTools => Memory => Profiles中,加载生成的两个heapsnapshot文件。

如下图所示,可以查看相应的内存占用情况:

浅谈Node的内存泄露问题

  • Summary:以构造函数名分类显示。
  • Comparison:比较多个快照之间的差异。
  • Containment:查看整个GC路径。
  • Statistics:以饼状图显示内存占用信息。

再看Statistics中关于内存占用的占比分析:

浅谈Node的内存泄露问题

再看Comparison中对比多个快照之间的差异。(可以很明显的看出增加的部分)

浅谈Node的内存泄露问题

5、内存分析的意义

从商业的角度来说,有时候我们无法通过代码,直观的看到内存泄露相关的信息,而这种内存分析的方式,给了我们解决问题的思路。

在现代化的业务开发中,内存监测是一种必要的工具,掌握了基本的原理,有助于我们分析和理解node性能分析的平台型工具。更有助于我们对node的理解。

到此这篇关于浅谈Node的内存泄露的文章就介绍到这了!


Tags in this post...

NodeJs 相关文章推荐
跟我学Nodejs(三)--- Node.js模块
May 25 NodeJs
轻松创建nodejs服务器(9):实现非阻塞操作
Dec 18 NodeJs
NodeJS学习笔记之Connect中间件模块(一)
Jan 27 NodeJs
nodejs实现邮件发送服务实例分享
Mar 29 NodeJs
使用nodejs爬取前程无忧前端技能排行
May 06 NodeJs
nodejs处理图片的中间件node-images详解
May 08 NodeJs
ajax +NodeJS 实现图片上传实例
Jun 06 NodeJs
浅析 NodeJs 的几种文件路径
Jun 07 NodeJs
nodejs+mongodb+vue前后台配置ueditor的示例代码
Jan 02 NodeJs
Nodejs中crypto模块的安全知识讲解
Jan 03 NodeJs
nodejs中各种加密算法的实现详解
Jul 11 NodeJs
分享node.js实现简单登录注册的具体代码
Apr 26 NodeJs
分享node.js实现简单登录注册的具体代码
Apr 26 #NodeJs
分享五个Node.js开发的优秀实践 
Apr 07 #NodeJs
Node.js实现爬取网站图片的示例代码
NodeJs使用webpack打包项目的方法详解
Feb 28 #NodeJs
node快速搭建后台的实现步骤
nodejs利用readline提示输入内容实例代码
详解NodeJS模块化
You might like
PHP配置心得包含MYSQL5乱码解决
2006/11/20 PHP
php结合ajax实现赞、顶、踩功能实例
2014/05/12 PHP
PHP callback函数使用方法和注意事项
2015/01/23 PHP
PHP依赖注入(DI)和控制反转(IoC)详解
2017/06/12 PHP
php实现websocket实时消息推送
2018/03/30 PHP
PHP bin2hex()函数基础实例讲解
2019/02/11 PHP
JAVASCRIPT 对象的创建与使用
2021/03/09 Javascript
设置下载不需要倒计时cookie(倒计时代码)
2008/11/19 Javascript
JS自动缩小超出大小的图片
2012/10/12 Javascript
jQuery实现鼠标可拖动调整表格列宽度
2014/05/26 Javascript
JavaScript中的6种运算符总结
2014/10/16 Javascript
javascript实现textarea中tab键的缩排处理方法
2015/06/26 Javascript
JS实现选项卡实例详解
2015/11/17 Javascript
JS获取字符串实际长度(包含汉字)的简单方法
2016/08/11 Javascript
js鼠标按键事件和键盘按键事件用法实例汇总
2016/10/03 Javascript
基于jquery实现的鼠标悬停提示案例
2016/12/11 Javascript
JS获取鼠标坐标并且根据鼠标位置不同弹出不同内容
2017/06/12 Javascript
node.js + socket.io 实现点对点随机匹配聊天
2017/06/30 Javascript
关于在mongoose中填充外键的方法详解
2017/08/14 Javascript
Element-ui DatePicker显示周数的方法示例
2019/07/19 Javascript
JavaScript实现更换背景图片
2019/10/18 Javascript
Python统计列表中的重复项出现的次数的方法
2014/08/18 Python
python matplotlib 在指定的两个点之间连线方法
2018/05/25 Python
利用Python将每日一句定时推送至微信的实现方法
2018/08/13 Python
python的pstuil模块使用方法总结
2019/07/26 Python
selenium+PhantomJS爬取豆瓣读书
2019/08/26 Python
印尼购物网站:iLOTTE
2019/10/16 全球购物
ORACLE第二个十问
2013/12/14 面试题
黄河的主人教学反思
2014/02/07 职场文书
走群众路线剖析材料
2014/10/09 职场文书
教师作风整改措施思想汇报
2014/10/12 职场文书
2015年爱牙日活动总结
2015/02/05 职场文书
乒乓球比赛通知
2015/04/27 职场文书
Python打包为exe详细教程
2021/05/18 Python
浅谈PostgreSQL表分区的三种方式
2021/06/29 PostgreSQL
MySQL修炼之联结与集合浅析
2021/10/05 MySQL