使用 memwatch-node 检测闭包的内存泄漏。

11

我的Node.js项目存在内存泄漏问题,我已经在闭包中将变量设置为null,我的意思是,我知道像下面这样的代码:

var a = 0;
var b = 1;
var c = 0;
example_func(c, func(){
    console.log(b);
});

会导致内存泄漏,所以我添加了一些代码将这些变量设置为 null;

var a = 0;
var b = 1;
var c = 0;
example_func(c, func(){
    console.log(b);
    a = null;
    b = null;
    c = null;
});

但是我仍然有内存泄漏问题,所以我尝试使用memwatch-node来找出我的代码哪里出了问题。

结果显示closure导致了内存泄漏,但没有足够的指示来确定泄漏的具体位置。

我得到的 JSON 数据如下:

 { what: 'Closure',
   '+': 12521,
   size: '520.52 kb',
   '-': 5118,
   size_bytes: 533016 },
我想知道哪个闭包泄漏了,能否提供更具体的细节?
我已经为所有的闭包指定名称,但仍然无效。

那么哪种对象会这样做呢?我没有自己设置“闭包”。 - bxshi
好的,无论如何还是谢谢。我已经添加了一些细节。 - bxshi
node-memwatch 中与 closure 相关的源代码位于 src/heapdiff.cc 的第 171 行,代码如下:case HeapGraphNode::kClosure: type.append("Closure"); break;,其中 kClosure 是由 V8 引擎定义的。 - bxshi
是的,我可以看出特定的Closure报告会非常有用,但目前memwatch的开发状态只能批量报告闭包泄漏。我认为你可能需要手动检测潜在的泄漏。一旦发现,你可以尝试使用JavaScript略微笨拙的delete运算符而不是使用null进行空值处理 - 这将清除符号表中的条目。顺便说一句,现在问题好多了。 - Beetroot-Beetroot
1
另一种方法:一旦您决定了要针对哪些函数,有时可以组织代码,使闭包仅包含最少量的变量以使其正常工作。重新组织需要一定的技巧,并属于“更多的艺术而非科学”类别。如果您正在使用构造函数/类,则此练习可以测试您对继承的理解。 - Beetroot-Beetroot
显示剩余3条评论
1个回答

2
您无法更具体地了解哪个闭包。 Memwatch获取v8堆的转储,然后对其进行差异并报告泄漏,如果在5次连续垃圾收集事件之后,该对象类型计数继续增长,则会报告泄漏。

此外,我认为您对闭包的理解存在一些困惑。MDN上的闭包页面提供了很好的描述。闭包不是变量,而是一种作用域,使函数能够保留引用并在代码的某个部分中继续工作,在那些变量引用在其他情况下不可用的情况下使用。

如果传递函数并保留对该函数的引用,则其闭包可能引用其他闭包。因此,单个闭包可能包含很多内容。

请执行以下操作:禁用您的代码部分,直到memwatch停止抱怨。然后,查看该代码。如果您仍然感到困惑,请在此问题中发布更多详细信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接