您经常在网络上读到使用闭包是 JavaScript 内存泄漏的一大来源。大多数时候,这些文章提到混合脚本代码和 DOM 事件,其中脚本指向 DOM,反之亦然。
我知道关闭可能是个问题。
但是 Node.js 呢?在这里,我们自然没有 DOM - 所以不会像浏览器那样出现内存泄漏的副作用。
闭包还有哪些其他问题?任何人都可以详细说明或指出一个很好的教程吗?
请注意,此问题明确针对 Node.js,而不是浏览器。
最佳答案
This question询问类似的事情。基本上,这个想法是,如果你在回调中使用闭包,你应该在完成后“取消订阅”回调,以便 GC 知道它不能再次调用。这对我来说很有意义;如果你有一个闭包等待被调用,GC 将很难知道你已经完成了它。通过从回调机制中手动移除闭包,它会变为未引用并可供收集。
此外,Mozilla 发布了 a great article on finding memory leaks in Node.js代码。我假设如果您尝试他们的一些策略,您可以找到表达泄漏行为的代码部分。最佳做法很好,但我认为了解您的程序需求并根据您的经验观察提出一些个性化的最佳做法会更有帮助。
以下是 Mozilla 文章的简短摘录:
- Jimb Esser’s
node-mtrace
, which uses the GCCmtrace
utility to profile heap usage.- Dave Pacheco’s
node-heap-dump
takes a snapshot of the V8 heap and serializes the whole thing out in a huge JSON file. It includes tools to traverse and investigate the resulting snapshot in JavaScript.- Danny Coates’s
v8-profiler
andnode-inspector
provide Node bindings for the V8 profiler and a Node debugging interface using the WebKit Web Inspector.- Felix Gnass’s fork of the same that un-disables the retainers graph
- Felix Geisendörfer’s Node Memory Leak Tutorial is a short and sweet explanation of how to use the
v8-profiler
andnode-debugger
, and is presently the state-of-the-art for most Node.js memory leak debugging.- Joyent’s SmartOS platform, which furnishes an arsenal of tools at your disposal for debugging Node.js memory leaks
this question 的答案基本上说你可以通过将 null
分配给闭包变量来帮助 GC。
var closureVar = {};
doWork(function callback() {
var data = closureVar.usefulData;
// Do a bunch of work
closureVar = null;
});
在函数返回时在函数中声明的任何变量都会消失,除了在其他闭包中使用的变量。在这个例子中,closureVar
必须在内存中,直到 callback()
被调用,但是谁知道什么时候会发生呢?调用回调后,您可以通过将闭包变量设置为 null 来向 GC 提供提示。
免责声明:正如您从下面的评论中看到的那样,有一些 SO 用户说这些信息已经过时并且对于 Node.js 而言无关紧要。我对此还没有明确的答案;我只是发布我在网络上找到的内容。
关于node.js - JavaScript 中的内存泄漏和关闭 - 何时以及为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19550253/