使用 memwatch-node 识别闭包的内存泄漏

Posted

技术标签:

【中文标题】使用 memwatch-node 识别闭包的内存泄漏【英文标题】:identify memory leak of closure with memwatch-node 【发布时间】:2012-11-27 17:18:52 【问题描述】:

我的 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 ,

我想知道是否可以获得有关哪个闭包泄漏的更多具体细节。

我已为所有闭包指定了名称,但仍然无法正常工作。

【问题讨论】:

这是一个对象字面量。就其本身而言,它与“闭包”无关,除了将其属性之一设置为字符串“闭包”,也可能是“1982 Datsun Cherry”。 那么哪种对象会这样做呢?我不会自己设置“关闭”。 是的,我很尴尬,我现在可以更好地了解您的问题。我已经查看了 memwatch 文档,但在差异报告中找不到 what: 'Closure' 部分的证据。 This 表示报告了闭包泄漏,但不是以这种方式。这有点令人困惑。 好吧,无论如何,谢谢。我已经添加了一些细节。 另一种方法:一旦确定了要定位的函数,有时可以组织代码,使闭包仅包含最少的变量以使其工作。重组需要一些技巧,属于“艺术多于科学”的范畴。如果你正在使用构造函数/类,这个练习可以测试你对继承的理解。 【参考方案1】:

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

另外,我相信您对什么是闭包感到困惑。 The MDN page on closures 给出了很好的描述。闭包不是一个变量,而是一个作用域,它使函数能够保留引用并在这些变量引用原本不可用的代码部分中使用时继续工作。

如果你传递函数保持对该函数的引用,它的闭包可能会引用其他闭包。所以,你可能有一个闭包,里面可能有很多东西。

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

【讨论】:

以上是关于使用 memwatch-node 识别闭包的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Navigate the Timeline Pane

美团外卖服务端的测试面试题居然泄……泄……泄……泄密了

美团外卖服务端的测试面试题居然泄……泄……泄……泄密了

重点突破——如何快速识别并解决“闭包问题”?

识别并避免 Js 内存泄漏,跟低级缺陷say goodbye,让老总对你刮目相看

闭包会造成内存泄漏吗?