浅谈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 相关文章推荐
使用upstart把nodejs应用封装为系统服务实例
Jun 01 NodeJs
基于NodeJS的前后端分离的思考与实践(一)全栈式开发
Sep 26 NodeJs
Nodejs极简入门教程(三):进程
Oct 27 NodeJs
nodejs爬虫抓取数据之编码问题
Jul 03 NodeJs
初探nodeJS
Jan 24 NodeJs
实例分析nodejs模块xml2js解析xml过程中遇到的坑
Mar 18 NodeJs
nodejs multer实现文件上传与下载
May 10 NodeJs
Nodejs中Express 常用中间件 body-parser 实现解析
May 22 NodeJs
nodejs超出最大的调用栈错误问题
Dec 27 NodeJs
CentOS7中源码编译安装NodeJS的完整步骤
Oct 13 NodeJs
nodejs中函数的调用实例详解
Oct 31 NodeJs
nodejs和react实现即时通讯简易聊天室功能
Aug 21 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操作xml
2013/10/27 PHP
php-perl哈希算法实现(times33哈希算法)
2013/12/30 PHP
php绘图之生成饼状图的方法
2015/01/24 PHP
PHP常用工具函数小结【移除XSS攻击、UTF8与GBK编码转换等】
2019/04/27 PHP
Firefox outerHTML实现代码
2009/06/04 Javascript
javascript中的107个基础知识收集整理 推荐
2010/03/29 Javascript
jQuery动态添加删除select项(实现代码)
2013/09/03 Javascript
jQuery实现新消息在网页标题闪烁提示
2015/06/23 Javascript
js代码实现无缝滚动(文字和图片)
2015/08/20 Javascript
el表达式 写入bootstrap表格数据页面的实例代码
2017/01/11 Javascript
详解JSON Web Token 入门教程
2018/07/30 Javascript
微信小程序实现九宫格抽奖
2020/04/15 Javascript
详解javascript中的Error对象
2019/04/25 Javascript
vue 防止页面加载时看到花括号的解决操作
2020/11/09 Javascript
微信小程序实现modal弹出框遮罩层组件(可带文本框)
2020/12/20 Javascript
[35:44]2014 DOTA2华西杯精英邀请赛 5 24 iG VS VG
2014/05/26 DOTA
python缩进区别分析
2014/02/15 Python
python之wxPython应用实例
2014/09/28 Python
python简单判断序列是否为空的方法
2015/06/30 Python
深入解析Python中的线程同步方法
2016/06/14 Python
Python标准库之collections包的使用教程
2017/04/27 Python
Python 循环语句之 while,for语句详解
2018/04/23 Python
pip已经安装好第三方库但pycharm中import时还是标红的解决方案
2020/10/09 Python
Wolford法国官网:奥地利奢侈内衣品牌
2020/08/11 全球购物
.NET面试题:什么是反射
2016/09/30 面试题
项目负责人任命书
2014/06/04 职场文书
小学绿色学校申报材料
2014/08/23 职场文书
志愿者爱心公益活动策划方案
2014/09/15 职场文书
公务员保密工作承诺书
2015/05/04 职场文书
2015年幼师个人工作总结
2015/10/15 职场文书
八年级语文教学反思
2016/03/03 职场文书
CSS 还能这样玩?奇思妙想渐变的艺术
2021/04/27 HTML / CSS
浅谈Python中的函数(def)及参数传递操作
2021/05/25 Python
浅谈Java父子类加载顺序
2021/08/04 Java/Android
Apache Hudi数据布局黑科技降低一半查询时间
2022/03/31 Servers
MySQL 字符集 character
2022/05/04 MySQL