Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

garbage collection with node.js

I was curious about how the node.js pattern of nested functions works with the garbage collector of v8. here's a simple example

readfile("blah", function(str) {    var val = getvaluefromstr(str);    function restofprogram(val2) { ... } (val) }) 

if restofprogram is long-running, doesn't that mean that str will never get garbage collected? My understanding is that with node you end up with nested functions a lot. Does this get garbage collected if restofprogram was declared outside, so str could not be in scope? Is this a recommended practice?

EDIT I didn't intend to make the problem complicated. That was just carelessness, so I've modified it.

like image 201
Vishnu Avatar asked Mar 16 '11 13:03

Vishnu


People also ask

How do I run a garbage collector in node JS?

If you launch the node process with the --expose-gc flag, you can then call global. gc() to force node to run garbage collection. Keep in mind that all other execution within your node app is paused until GC completes, so don't use it too often or it will affect performance.

Can you force garbage collection in JavaScript?

As of 2019, it is not possible to explicitly or programmatically trigger garbage collection in JavaScript.

How often does node garbage collect?

Depends on your code and how much garbage is created, but garbage collection calls each couple of seconds is pretty normal as default JS code usually creates objects constantly. If you have a problem with GC, try to reduce object allocations and just modify their properties, when needed.

How do I stop memory leaks in node JS?

Avoid Accidental Globals This could be the result of a typo and could lead to a memory leak. Another way could be when assigning a variable to this within a function in the global scope. To avoid issues like this, always write JavaScript in strict mode using the 'use strict'; annotation at the top of your JS file.


1 Answers

Simple answer: if value of the str is not referenced from anywhere else (and str itself is not referenced from restofprogram) it will become unreachable as soon as the function (str) { ... } returns.

Details: V8 compiler distinguishes real local variables from so called context variables captured by a closure, shadowed by a with-statement or an eval invocation.

Local variables live on the stack and disappear as soon as function execution completes.

Context variables live in a heap allocated context structure. They disappear when the context structure dies. Important thing to note here is that context variables from the same scope live in the same structure. Let me illustrate it with an example code:

function outer () {   var x; // real local variable   var y; // context variable, referenced by inner1   var z; // context variable, referenced by inner2    function inner1 () {     // references context      use(y);   }    function inner2 () {     // references context      use(z);   }    function inner3 () { /* I am empty but I still capture context implicitly */ }     return [inner1, inner2, inner3]; } 

In this example variable x will disappear as soon as outer returns but variables y and z will disappear only when both inner1, inner2 and inner3 die. This happens because y and z are allocated in the same context structure and all three closures implicitly reference this context structure (even inner3 which does not use it explicitly).

Situation gets even more complicated when you start using with-statement, try/catch-statement which on V8 contains an implicit with-statement inside catch clause or global eval.

function complication () {   var x; // context variable    function inner () { /* I am empty but I still capture context implicitly */ }    try { } catch (e) { /* contains implicit with-statement */ }    return inner; } 

In this example x will disappear only when inner dies. Because:

  • try/catch-contains implicit with-statement in catch clause
  • V8 assumes that any with-statement shadows all the locals

This forces x to become a context variable and inner captures the context so x exists until inner dies.

In general if you want to be sure that given variable does not retain some object for longer than really needed you can easily destroy this link by assigning null to that variable.

like image 126
Vyacheslav Egorov Avatar answered Oct 05 '22 21:10

Vyacheslav Egorov