最近遇到一个node项目有内存泄露的问题,内存会有个周期性的升高下降。
收集数据
- 工具选择
常用node内存分析工具有heapdump, Easy-monitor, v8-profiler-rs等,这次使用的是heapdump。
- 代码
function collectMemory() {
heapdump.writeSnapshot('./' + Date.now() + '.heapsnapshot')
}
setInterval(collectMemory, 60000)
将上面代码放入入口文件,1分钟后就可以看到内存快照被打印了。如果内存变化不大,可以自行调整打印的间隔。
分析数据
-
导入devtool
打开
chrome://inspect
,点击node专用
再点击 memory,点击load或者左侧空白区域右击load按时间顺序加载内存快照
-
寻找线索
主要关注comparion,选择一个快照及对比的快照
然后可以看到 size delta列的数据变化,从前几个入手,system和array都没有找到什么有效的信息,看到string的时候感觉是一些log输出,并且下面的详细信息里有个logger函数。
解决方法
回到项目里,有三处log相关的函数,一个是用自定义log函数替换了默认的console.log,第二个是‘nestjs’的logger,最后一个是第三方包‘yog-log’。
先是注释了自定义的log函数,但问题仍然存在;
nestjs的logger也先排除了,毕竟是一个比较主流的框架,在很多项目使用,有问题应该早爆出来了;
那就只剩‘yog-log’了,到它的github看了下,有一个issue说到domain可能导致的内存泄露,顺着这个就去node上看了下domain这个包,显示要被废弃了。接着又搜了下,有一些关于domain导致内存泄露的问题,‘yog-log’的源码中确实有用到了domian以及定义了logger的函数,到这基本就定位到问题了。注释后跑了下,内存没有那么大的变化了。
放到服务器内存也不是一直上升了。
彩蛋
写文章的时候发现了另外一个分析工具v8-profiler-rs,增加了可视化和辅助分析报告,基本一眼就能看到哪个函数导致了泄漏。
(v8-profiler-rs的可视化页面,满屏的logger已经很明显了)