浅谈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中使用多线程编程的方法实例
Mar 24 NodeJs
解析NodeJs的调试方法
Dec 11 NodeJs
async/await与promise(nodejs中的异步操作问题)
Mar 03 NodeJs
nodejs搭建本地http服务器教程
Mar 13 NodeJs
nodeJS微信分享
Dec 20 NodeJs
nodejs实现一个word文档解析器思路详解
Aug 14 NodeJs
nodejs遍历文件夹下并操作HTML/CSS/JS/PNG/JPG的方法
Nov 01 NodeJs
nodejs搭建本地服务器并访问文件操作示例
May 11 NodeJs
nodejs实现日志读取、日志查找及日志刷新的方法分析
May 20 NodeJs
Nodejs在局域网配置https访问的实现方法
Oct 17 NodeJs
nodeJs项目在阿里云的简单部署
Nov 27 NodeJs
nodejs利用readline提示输入内容实例代码
Jul 15 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生成HTML静态页面实例代码
2008/08/31 PHP
php中禁止单个IP与ip段访问的代码小结
2012/07/04 PHP
thinkPHP5 tablib标签库自定义方法详解
2017/05/10 PHP
JavaScript 动态创建VML的方法
2009/10/14 Javascript
javascript中的prototype属性使用说明(函数功能扩展)
2010/08/16 Javascript
javscript对象原型的一些看法
2010/09/19 Javascript
Web跨浏览器进程通信(Web跨域)
2013/04/17 Javascript
jquery提交form表单时禁止重复提交的方法
2014/02/13 Javascript
jQuery获取DOM节点实例分析(2种方式)
2015/12/15 Javascript
js获取及修改网页背景色和字体色的方法
2015/12/29 Javascript
Angularjs中的事件广播 —全面解析$broadcast,$emit,$on
2016/05/17 Javascript
详解jQuery简单的表格应用
2016/12/16 Javascript
jQuery实现手机号正则验证输入及自动填充空格功能
2018/01/02 jQuery
layui 给数据表格加序号的方法
2018/08/20 Javascript
React注册倒计时功能的实现
2018/09/06 Javascript
vue 集成 vis-network 实现网络拓扑图的方法
2019/08/07 Javascript
Javascript执行流程细节原理解析
2020/05/14 Javascript
JavaScript实现像雪花一样的Hexaflake分形
2020/07/07 Javascript
解决vant-UI库修改样式无效的问题
2020/11/03 Javascript
Python提取网页中超链接的方法
2016/09/18 Python
浅谈Python爬取网页的编码处理
2016/11/04 Python
python2与python3的print及字符串格式化小结
2018/11/30 Python
Python设计模式之迭代器模式原理与用法实例分析
2019/01/10 Python
python实现扫描ip地址的小程序
2019/04/16 Python
Django使用Celery加redis执行异步任务的实例内容
2020/02/20 Python
10种CSS3实现的loading动画,挑一个走吧?
2020/11/16 HTML / CSS
MYSQL基础面试题
2012/05/13 面试题
英语专业毕业生自荐信范文
2013/12/31 职场文书
教师业务学习制度
2014/01/25 职场文书
《将心比心》教学反思
2014/04/08 职场文书
拓展策划方案
2014/06/03 职场文书
公司门卫岗位职责范本
2014/07/08 职场文书
四风问题查摆材料
2014/08/25 职场文书
纪委书记群众路线整改措施思想汇报
2014/10/09 职场文书
2016年教师节感恩寄语
2015/12/04 职场文书
ubuntu安装jupyter并设置远程访问的实现
2022/03/31 Python