JavaScript memory leaks and closures - when and why?

You often read on the Internet that using closures is a massive source of memory leaks in JavaScript. In most cases, these articles are about mixing script code and DOM events, where the script points to the DOM and vice versa.

I understand that closing can be a problem.

But what about Node.js? Here, of course, we do not have a DOM, so there is no way to have the side effects of a memory leak, as in browsers.

What else could be closing problems? Can anyone develop or point me a good tutorial on this?

Please note that this question is clearly aimed at Node.js, not the browser.

+50
closures memory-leaks
Oct 23 '13 at 19:04 on
source share
3 answers

This question asks about something similar. Essentially, the idea is that if you use closure in a callback, you must unsubscribe from the callback when you're done so that the GC knows that it cannot be called again. It makes sense to me; if you have a circuit waiting for a call, it will be difficult for the GC to know that you are done with it. By manually removing the closure from the callback mechanism, it becomes unconnected and available for collection.

In addition, Mozilla published an excellent article on finding memory leaks in Node.js. I assume that if you try some of their strategies, you may find parts of your code that express a leak. Best practices are good and all, but I think it’s more useful to understand the needs of your program and come up with some personalized best practices based on what you can observe empirically.

Here is a brief excerpt from an article on Mozilla:

  • Jimb Essers node-mtrace , which uses the GCC mtrace utility to profile heap usage.
  • Dave Pachecos node-heap-dump takes a snapshot of the V8 heap and serializes it all into a huge JSON file. It includes tools for viewing and examining the resulting snapshot in JavaScript.
  • Danny Coatess v8-profiler and node-inspector provide Node bindings for the V8 profiler and Node debugging interface using WebKit Web Inspector.
  • Felix Gnasss from the same fork that disables the latch graph
  • The Felix Geisendörfers node memory leak tutorial is a short and enjoyable explanation of how to use v8-profiler and node-debugger , and is currently up-to-date for debugging most memory leaks in Node.js.
  • The Joyents SmartOS platform, which provides you with an arsenal of tools for troubleshooting memory leaks in Node.js.



The answers to this question basically say that you can help the GC by setting null to closure variables.

 var closureVar = {}; doWork(function callback() { var data = closureVar.usefulData; // Do a bunch of work closureVar = null; }); 

Any variables declared inside the function will disappear when the function returns, except for those used in other closures. In this example, closureVar should be in memory before callback() , but who knows when this will happen? After the callback has been called, you can give a hint to GC by setting your closure variable to null.

DISCLAIMER : As you can see from the comments below, there are some SO users who say that this information is outdated and inconsequential for Node.js. I do not have a final answer to this question; I just publish what I found on the network.

+36
Oct 30 '13 at 14:47
source share

You can find a good example and explanation on this David Glasser blog .

Well, here it is (I added a few comments):

 var theThing = null; var cnt = 0; // helps us to differentiate the leaked objects in the debugger var replaceThing = function () { var originalThing = theThing; var unused = function () { if (originalThing) // originalThing is used in the closure and hence ends up in the lexical environment shared by all closures in that scope console.log("hi"); }; // originalThing = null; // <- nulling originalThing here tells V8 gc to collect it theThing = { longStr: (++cnt) + '_' + (new Array(1000000).join('*')), someMethod: function () { // if not nulled, original thing is now attached to someMethod -> <function scope> -> Closure console.log(someMessage); } }; }; setInterval(replaceThing, 1000); 

Please try with zero and non-zeroing originalThing in Chrome Dev Tools (timeline tab, view memory, click record) Please note that the above example applies to the browser and Node.js environments.

I also thank Vyacheslav Egorov especially.

+10
Mar 03 '14 at 12:29
source share

I must disagree with the closure causing memory leaks. This may be true for older versions of IE due to its crappy garbage collection. Please read this article from Douglas Crockford, which clearly indicates what happens with a memory leak.

They say that she lost her memory, which was not corrected.

Leaks are not a problem; efficient garbage collection. Leaks can occur both in the browser and in server-side JavaScript applications. Take the V8 as an example. In the browser, garbage collection occurs on the tab when switching to another window / tab. The leak is connected when idling. Tabs may be in standby mode.

Everything is not so simple on the server. Leaks can occur, but the GC is not so cost-effective. Servers cannot afford GC often, or this will affect performance. When the node process reaches a specific memory usage, it starts in the GC. Then the leaks will be periodically removed. But leaks can still happen faster, which leads to program crashes.

+2
Oct 24 '13 at 10:57
source share



All Articles