如何在Node.js中检测内存泄漏
发布网友
发布时间:2022-04-26 17:58
我来回答
共2个回答
热心网友
时间:2022-04-22 18:40
工具
工欲善其事必先利其器,在排查时,我们还是需要一些工具来帮忙的。
devTool
这个是今年初出的 Node.js 调试工具,基于 Electron 将 Node.js 和 Chromium 的功能融合在了一起。操作起来比 node-inspector 方便,开放的 Timeline 功能还是比较实用的,虽然不是实时显示。
仅需要 devtool xxx.js,还可以通过 .devtoolrc 来进行参数定制,具体见 GitHub
heapmp + chrome devTool
这个是比较传统的定位内存泄漏的组合。heapmp 可以直接在代码中调用生成内存快照,然后将快照文件导入到 chrome devTool 进行分析,之后操作其实和前者就差不多了。不过,这个方案和前者有一点区别就是,前者实际还是在浏览器环境中,所以生成的内存快照会有一些 DOM 对象的存在,会有一定的干扰。而这个方案,是直接调用底层 V8 的方法,生成的快照只有 Node.js 环境中的对象。
memwatch
这个可以在代码里直接使用,实时检测内存动态,当发生内存泄漏的时候,会触发 ‘leak’ 事件,会传递当前的堆状态,配合 heapmp 有奇效。详见 memwatch。
流程
一、重现问题
对于垃圾回收,V8 引擎有很复杂的逻辑来决定什么时候进行回收。很多时候,当我们发现 Node.js 进程所使用的内存快速增长的时候,并不能确定是否是内存泄漏导致的,很有可能是程序设计问题,导致内存的不合理利用。只有当垃圾回收触发,未使用内存被释放后,内存增长还在持续,我们才能确定是发生了内存泄漏。
隐藏的内存泄漏问题,大多是有触发条件的,重现问题是需要这些条件的,所以我们在平时写代码的时候,可以将一些重要环节的参数细节打印在 log 中,这样我们在重现问题是就不会摸不着头脑,乱试一气。
有了参数可以用来重现问题,接下来要确定问题。我们要确定,这部分内存是否没有被 GC 正确释放。那么问题来了,我们如何知道程序进行了垃圾回收呢?很显然,等待并不是办法,我们要主动。
在 Node.js 的启动参数中,提供了暴露手动调用 GC 方法的参数,即 --expose-gc。我们用这个参数来启动应用后,就可以在代码中调用 global.gc() 手动触发垃圾回收操作。同时,使用 process.memoryUsage().heapUsed 获取进程运行时所占用的内存。如果 GC 之后,内存依然没有下降,就可以确定是内存泄露了。
二、生成内存快照
既然内存是问题,我们就需要获取程序运行的内存快照来帮助定位问题。但内存快照并不是随便打得,是有一定技巧的。
我们至少要生成三次内存快照,才能更好的定位问题。这三次中又一次要在问题出现前生成,之后可以在问题持续的过程中生成两次或更多。
为什么要这样做呢?理解起来很简单。第一次是为了获取正常情况下的堆栈信息,而在问题出现后,堆栈信息一定会发生变化,有了第一次的信息,我们才好进行后面的比对,过滤一些无用的信息。而后两次的快照,用来比对某一对象的堆栈变化,来确定是否是有问题的对象。下面会详细应用到。
三、定位问题
用 devTool 的可以忽略下面的过程:
打开 Chrome Devtools ,进入到 Profiles 选项卡,点 Load 按钮,加载之前生成的快照。
对于内存快照,有四个视图,Summary,Comparison,Containment,Statistics,这里面常用的是前三个。
在 Summary 视图中,我们可以看到当前快照的全部信息,以及多个快照之间的信息。在列表里显示的都是对象的构造函数名字,可以先忽略被括号包裹的对象,优先观察其他的对象,最后再来看他们。后面的 shallow size 表示的是对象自身的大小,retained size 表示的是对象和它依赖对象的大小,一般是 GC 不可达的。
在 Comparison 视图中,我们可以进行多个快照之间的对比,这个用处比较大,如果我们将前两次快照进行对比,可能比较快速的定位出问题的对象。注意观察 New、Deleted、Delta,如果是内存泄漏的对象,可能是一直在 New,而没有 Deleted。
在 Containment 视图中,我们可以查看整个 GC 路径,当然一般不会用到。因为展开在 Summary 和 Comparison 列举的每一项,都可以看到从 GC roots 到这个对象的路径。通过这些路径,你可以看到这个对象的句柄被什么持有,从而定位问题产生的原因。值的注意的是,其中背景色*的,表示这个对象在 Javascript 中还存在引用,所以可能没有被清除。如果是红色的,表示的是这个对象在 Javascript 中不存在引用,但是依然存活在内存中,一般常见于 DOM 对象,它们存放的位置和 Javascript 中对象还是有不同的,在 Node.js 中很少遇见。
热心网友
时间:2022-04-22 19:58
首先,我们检查了代码,发现所有的代码都是用new来分配内存,用delete来释放内存。那么,我们能够用一个全程替换,来替换掉所有的new和delete操作符吗?不能。因为代码的规模太大了,那样做除了浪费时间没有别的任何好处。好在我们的源代码是用C...
如何在Node.js中检测内存泄漏
node检测内存泄露条件模块memwatch npm install --save memwatch var memwatch = require('memwatch');memwatch.setup();memwatch.on('leak', function(info) { console.error('Memory leak detected: ', info);});
静态ip - StormProxies
"StormProxies是全球大数据IP资源服务商,其住宅代理网络由真实的家庭住宅IP组成,可为企业或个人提供满足各种场景的代理产品。点击免费测试(注册即送1G流量)StormProxies有哪些优势?1、IP+端口提取形式,不限带宽,IP纯净高匿;2、覆盖全球200+的国家与地区,超7000万住宅IP。3、高可靠性,24小时稳定运行,平均99.99%的可用率;4、性价比更高,便宜好用,单个IP也能享受最优价格,没有额外费用;5、易于使用,支持HTTP/HTTPS/SOCKS5协议,提供多种API参数,网络集成更快捷;6、客服全天在线为您排忧解难,并可根据您的业务需求制定更合适的代理…StormProxies是全球大数据IP资源服务商,其住宅代理网络由真实的家庭住宅IP组成,可为企业或个人提供满足各种场景的代理产品。点击免费测试(注册即送1G流量)StormProxies有哪些优势?1、IP+端口提取形式,不限带宽,IP纯净高匿;2、覆盖全球20...
如何定位Node.js的内存泄漏
而这个方案,是直接调用底层 V8 的方法,生成的快照只有 Node.js 环境中的对象。memwatch 这个可以在代码里直接使用,实时检测内存动态,当发生内存泄漏的时候,会触发 ‘leak’ 事件,会传递当前的堆状态,配合 heapdump 有奇效。二、定位问题:用 devTool 的可以忽略下面的过程:打开 Chrome Devtools ...
如何自己检查NodeJS的代码是否存在内存泄漏
运行我们的代码,磁盘上会产生一些.heapsnapshot的文件到/tmp目录下。现在,在Chrome浏览器中,启动开发者工具(在mac下的快捷键是alt+cmd+i),点击Profiles标签并点击Load按钮载入我们的快照。我们能够很清晰地发现原来leakyfunc()是内存泄漏的元凶。我们依然还可以通过对比两次记录中heapdump的不同来更加...
如何自己检查NodeJS的代码是否存在内存泄漏
我们需要做的是:跟踪所有的内存分配和交互引用以及内存释放。我们的源代码使用Visual C++写成,当然这种解决方法也可以很轻松的使用在别的C++代码里面。要做的第一件事情是重载new和delete操作符,它们将会在所有的代码中被使用到。我们在stdafx.h中,加入:ifdef _DEBUG inline void * __cdecl operator...
如何分析 Node.js 中的内存泄漏
三、事件监听 Node.js 的事件监听也可能出现的内存泄漏。例如对同一个事件重复监听,忘记移除(removeListener),将造成内存泄漏。这种情况很容易在复用对象上添加事件时出现,所以事件重复监听可能收到如下警告:(node:2752) Warning: Possible EventEmitter memory leak detected。11 haha listeners added。
使用Chrome开发者工具的Memory标签页分析内存泄漏问题
在调试模式下运行Node.js应用程序,访问chrome://inspect,如果在端口转发中配置了localhost:9229,那么此刻应该能够看到应用程序并对其进行调试。在JSStorefront应用程序中导致内存泄漏的一种最常见的错误是是订阅事件而不在组件被销毁后取消订阅。下面是一个防止这种内存泄漏的示例——关键在于检查代码并确保...
Node.js 应用故障排查手册 —— Node.js 性能平台使用指南
进程 CPU 高:收到 Node.js 应用进程 CPU 超过阈值告警时,在控制台对应实例点击 CPU Profile 按钮,生成 3 分钟的 CPU Profile 文件,分析 JS 函数执行情况,定位代码瓶颈。内存泄漏:收到 Node.js 应用进程堆内存超过阈值告警时,在控制台对应实例点击堆快照按钮,生成堆快照文件,分析堆空间占用情况...
node扩展 memwatch分析
memwatch是一个C++扩展,主要用于检测Node.js中的内存泄漏问题。它的基本用法包括配置文件binding.gyp,以及src目录下的多个源文件如heapdiff.cc、init.cc、memwatch.cc、util.cc。这些文件通过node模块系统在编译过程中找到依赖的nan目录。memwatch的入口函数在init.cc文件中,通过`NODE_MODULE(memwatch, ...
node.jsjavascriptruntime内存占用太高如何处理?
处理Node.js和JavaScript运行时内存占用过高的策略主要有以下几个方面:首先,排查并解决内存泄漏问题。内存泄漏是指程序执行过程中,不再使用的内存没有被正确释放,导致内存占用逐渐增加。可通过使用内存分析工具如heapdump、memwatch等来检测内存泄漏。其次,优化代码,减少内存使用。在编程时,可以应用优化...
什么是内存泄漏?
首先,你是如何申请的内存就如何释放,也就是说:Node* pNode = new Node;Node* arrNode = new Node[10];delete pNode;delete [] arrNode;//~ 堆管理器(应用程序的,也可以是系统的)会根据相应的记录删除你申请的内存 如果不显式释放从堆上申请的内存,那么在进程的整个生命期内,这块内存就...