浅谈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 相关文章推荐
PHPStorm 2020.1 调试 Nodejs的多种方法详解
Sep 17 NodeJs
nodejs实现HTTPS发起POST请求
Apr 23 NodeJs
nodejs创建web服务器之hello world程序
Aug 20 NodeJs
图片上传之FileAPI与NodeJs
Jan 24 NodeJs
Nodejs中Express 常用中间件 body-parser 实现解析
May 22 NodeJs
nodeJS实现简单网页爬虫功能的实例(分享)
Jun 08 NodeJs
Nodejs之http的表单提交
Jul 07 NodeJs
让nodeJS支持ES6的词法----babel的安装和使用方法
Jul 31 NodeJs
nodejs微信开发之自动回复的实现
Mar 17 NodeJs
nodejs搭建本地服务器并访问文件操作示例
May 11 NodeJs
Nodejs监控事件循环异常示例详解
Sep 22 NodeJs
nodejs中内置模块fs,path常见的用法说明
Nov 07 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
Syphon 使用方法
2021/03/03 冲泡冲煮
实用函数5
2007/11/08 PHP
linux下删除7天前日志的代码(php+shell)
2011/01/02 PHP
PHP优于Node.js的五大理由分享
2012/09/15 PHP
php 伪造ip以及url来路信息方法汇总
2014/11/25 PHP
动态表格Table类的实现
2009/08/26 Javascript
js removeChild 障眼法 可能出现的错误
2009/10/06 Javascript
js/jQuery对象互转(快速操作dom元素)
2013/02/04 Javascript
JavaScript基础篇之变量作用域、传值、传址的简单介绍与实例
2013/06/29 Javascript
纯javascript制作日历控件
2015/07/17 Javascript
bootstrap table小案例
2016/10/21 Javascript
Angular2入门--架构总览
2017/03/29 Javascript
vue 实现数字滚动增加效果的实例代码
2018/07/06 Javascript
微信小程序仿朋友圈发布动态功能
2018/07/15 Javascript
javascript数组去重方法总结(推荐)
2019/03/20 Javascript
模块化react-router配置方法详解
2019/06/03 Javascript
Promise扫盲贴
2019/06/24 Javascript
javascript实现抢购倒计时程序
2019/08/26 Javascript
浅谈Webpack4 Tree Shaking 终极优化指南
2019/11/18 Javascript
JS实现音乐导航特效
2020/01/06 Javascript
Python中不同进制互相转换(二进制、八进制、十进制和十六进制)
2015/04/05 Python
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
2018/01/26 Python
Python编程求质数实例代码
2018/01/31 Python
django框架模板语言使用方法详解
2019/07/18 Python
python中的反斜杠问题深入讲解
2019/08/12 Python
套娃式文件夹如何通过Python批量处理
2020/08/23 Python
Python 远程开关机的方法
2020/11/18 Python
Pytorch 中的optimizer使用说明
2021/03/03 Python
CSS3 :not()选择器实现最后一行li去除某种css样式
2016/10/19 HTML / CSS
localStorage、sessionStorage使用总结
2017/11/17 HTML / CSS
会计主管岗位职责
2014/01/03 职场文书
善意的谎言事例
2014/02/15 职场文书
个人借款协议书范本
2014/11/17 职场文书
2014年保管员工作总结
2014/11/18 职场文书
《天净沙·秋思》教学反思三篇
2019/11/02 职场文书
Ruby处理YAML和json数据
2022/04/18 Ruby