浅谈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 07 NodeJs
跟我学Nodejs(二)--- Node.js事件模块
May 21 NodeJs
Nodejs sublime text 3安装与配置
Jun 19 NodeJs
Nodejs中调用系统命令、Shell脚本和Python脚本的方法和实例
Jan 01 NodeJs
NodeJS学习笔记之MongoDB模块
Jan 13 NodeJs
nodejs中实现sleep功能实例
Mar 24 NodeJs
nodeJs爬虫获取数据简单实现代码
Mar 29 NodeJs
ubuntu编译nodejs所需的软件并安装
Sep 12 NodeJs
nodejs+mongodb aggregate级联查询操作示例
Mar 17 NodeJs
nodejs更改项目端口号的方法
May 13 NodeJs
Nodejs技巧之Exceljs表格操作用法示例
Nov 06 NodeJs
NodeJs内存占用过高的排查实战记录
May 10 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
自制汽车收音机天线:收听广播的技巧和方法
2021/03/02 无线电
繁体中文转换为简体中文的PHP函数
2006/10/09 PHP
如何用phpmyadmin设置mysql数据库用户的权限
2012/01/09 PHP
php基于session实现数据库交互的类实例
2015/08/03 PHP
Laravel5.1 框架路由基础详解
2020/01/04 PHP
CentOS7系统搭建LAMP及更新PHP版本操作详解
2020/03/26 PHP
基于jquery的blockui插件显示弹出层
2011/04/14 Javascript
js 弹出菜单/窗口效果
2011/10/30 Javascript
jquery图片放大镜功能的实例代码
2013/03/26 Javascript
js性能优化技巧
2015/11/29 Javascript
使用JavaScript实现一个小程序之99乘法表
2017/09/21 Javascript
浅谈webpack-dev-server的配置和使用
2018/05/17 Javascript
vue-cli项目修改文件热重载失效的解决方法
2018/09/19 Javascript
JavaScript常用数组操作方法,包含ES6方法
2020/05/10 Javascript
JS回调函数简单易懂的入门实例分析
2019/09/29 Javascript
微信小程序可滑动周日历组件使用详解
2019/10/21 Javascript
Vuex中实现数据状态查询与更改
2019/11/08 Javascript
javascript设计模式 ? 桥接模式原理与应用实例分析
2020/04/13 Javascript
jQuery实现评论模块
2020/08/19 jQuery
使用scrapy实现爬网站例子和实现网络爬虫(蜘蛛)的步骤
2014/01/23 Python
python检测远程udp端口是否打开的方法
2015/03/14 Python
Python爬虫爬取美剧网站的实现代码
2016/09/03 Python
python 截取 取出一部分的字符串方法
2017/03/01 Python
python PyTorch参数初始化和Finetune
2018/02/11 Python
python 读文件,然后转化为矩阵的实例
2018/04/23 Python
python删除文件夹下相同文件和无法打开的图片
2019/07/16 Python
django处理select下拉表单实例(从model到前端到post到form)
2020/03/13 Python
AmazeUI 加载进度条的实现示例
2020/08/20 HTML / CSS
建筑设计师岗位职责
2013/11/18 职场文书
初中班主任寄语
2014/04/04 职场文书
企业安全生产责任书
2014/04/14 职场文书
第二批党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
小学生教师节广播稿
2015/08/19 职场文书
咖啡厅里的创业计划书
2019/08/21 职场文书
python简单验证码识别的实现过程
2021/06/20 Python
日本动漫十大公认神作:第五现已全网禁播,《死亡笔记》在榜
2022/03/18 日漫