node.js中的闭包会导致内存泄漏

在尝试debuggingNodeJS中的内存泄漏时,我发现它非常困难(鉴于缺乏我知道的分析工具)。

我以为我会回到基础知识,并确保我明白如何在NodeJS中专门创build内存泄漏。 我对可能导致内存泄漏的闭包types感到困惑,并且不清楚垃圾收集器需要什么来释放内存。

你能给我一些基本模式的例子,会导致在Node.js内存泄漏?

不是一个“泄漏”,但这可能是一个常见的陷阱。

var fn = (function() { var a = "super long string ..."; var b = "useless value"; var c = "Hello, World!"; return function() { return c; }; })(); 

这将返回一个引用范围的函数,并且该范围中的每个局部variables将被保留,即使只需要其中的一个值。 这导致更多的内存使用比你需要,特别是如果你的函数使用一个小的variables,但有一个大的值,你不需要继续引用。


如何解决它?

简单的select是在你的函数结束时将你不关心的variables清空。 variables仍然在范围内,但他们的数据将被释放。

 var fn = (function() { var a = "super long string ..."; var b = "useless value"; var c = "Hello, World!"; // do stuff with a and b a = b = null; return function() { return c; }; })(); 

或者,你可以将任何使用临时variables的东西都分解成它自己的函数,这样它们的范围就可以被释放。 对于较大的项目来说,这是一个更好的解决方

 var doSetup = function() { var a = "super long string ..."; var b = "useless value"; // do stuff with a and b }; var fn = (function() { doSetup(); var c = "Hello, World!"; return function() { return c; }; })(); 
  1. 您可以使用节点检查器使用Chrome开发工具debugging节点应用程序。

  2. 接受的关于未使用的闭包variables的答案是错误的,因为在现代的JS引擎中,只有那些在内部函数中实际引用的variables才被包含在闭包范围中。 其余的都自动收集垃圾。 换句话说,这个理论条件决不会在Node中实际发生。

  3. 对于使用express的真实(也是相当常见的)示例,您可以创build中间件,为每个请求将文件加载到内存中,然后在该请求中抛出未处理的exception,捕获抛出的exception,然后不能退出进程。

抛出的exception将导致加载的请求资源徘徊,而不是在请求/响应周期结束时被清除。

发生exception时,如果没有退出进程,意味着不会像PM2或Forever那样closures并重新启动,Node将忽略错误并继续提供新的请求,就好像什么也没发生一样。 由于资源没有被清理,这个过程会消耗越来越多的内存,直到它拖垮了机器的性能,并最终耗尽空间来分配新的资源。

这显然会对用户体验产生负面影响。

另请参阅为什么exception会导致Node.js中的资源泄漏 。

来自: http : //google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml?showone=Closures#Closures

不过要记住的一点是,闭包保留了一个指向其封闭范围的指针。 因此,将闭包附加到DOM元素可能会产生循环引用,从而导致内存泄漏。 例如,在以下代码中:

 function foo(element, a, b) { element.onclick = function() { /* uses a and b */ }; } 

函数闭包保持对元素,a和b的引用,即使它从不使用元素。 由于元素也保留了对闭包的引用,所以我们有一个不会被垃圾收集清理的循环。 在这些情况下,代码的结构如下:

 function foo(element, a, b) { element.onclick = bar(a, b); } function bar(a, b) { return function() { /* uses a and b */ } }