提问者:小点点

如何在node.js中跟踪堆内对象以发现内存泄漏?


我有内存泄漏,我知道它在哪里(我想是这样的),但我不知道为什么会发生。负载测试以下endpoint(使用restify.js服务器)时发生内存泄漏:

server.get('/test',function(req,res,next){
    fetchSomeDataFromDB().done(function(err,rows){
        res.json({ items: rows })
        next()
    })
})

我非常肯定res对象没有被(垃圾回收器)释放。在每一个请求中,应用程序使用的内存都在增长。我做了一些附加测试:

var data = {}
for(var i = 0; i < 500; ++i) {
    data['key'+i] = 'abcdefghijklmnoprstuwxyz1234567890_'+i
}
server.get('/test',function(req,res,next){
    fetchSomeDataFromDB().done(function(err,rows){
        res._someVar = _.extend({},data)
        res.json({ items: rows })
        next()
    })
})

因此,在每个请求中,我都将big object分配给res对象作为其属性。我观察到,有了这个附加属性,内存增长得快得多。在60秒内每完成1000个请求,内存会增加100MB。在下一次相同的测试之后,内存再次增长100MB,以此类推。现在,当我知道res对象没有被“释放”时,我如何跟踪什么仍然保持对res的引用?假设我将执行堆快照--如何找到引用RE的内容?

10个请求之间的堆对比截图:

实际上,instance.dao似乎正在泄漏??这个类属于ORM,我正在使用它来查询DB...你觉得呢?

多一个按#delta排序的相同coparison屏幕:


共1个答案

匿名用户

GC似乎还没有收集对象,因为您没有在代码中的任何地方泄漏res。尝试使用--expose-gc节点参数运行脚本,然后设置定期调用gc();的间隔。这将迫使GC运行而不是懒惰。

如果之后您发现确实有内存泄漏,您可以使用heapdump模块之类的工具来使用Chrome developer堆检查器来查看哪些对象占用了空间。