[ACCEPTED]-garbage collection with node.js-v8
Simple answer: if value of the str
is not referenced 31 from anywhere else (and str
itself is not referenced 30 from restofprogram
) it will become unreachable as soon 29 as the function (str) { ... }
returns.
Details: V8 compiler distinguishes 28 real local variables from so called context variables 27 captured by a closure, shadowed by a with-statement 26 or an eval
invocation.
Local variables live 25 on the stack and disappear as soon as function 24 execution completes.
Context variables live 23 in a heap allocated context structure. They 22 disappear when the context structure dies. Important 21 thing to note here is that context variables 20 from the same scope live in the same structure. Let 19 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 18 this example variable x
will disappear as 17 soon as outer
returns but variables y
and z
will 16 disappear only when both inner1
, inner2
and inner3
die. This happens 15 because y
and z
are allocated in the same 14 context structure and all three closures 13 implicitly reference this context structure 12 (even inner3
which does not use it explicitly).
Situation 11 gets even more complicated when you start 10 using with-statement, try/catch-statement which on V8 9 contains an implicit with-statement inside catch 8 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 7 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 6 forces x
to become a context variable and 5 inner
captures the context so x
exists until inner
dies.
In 4 general if you want to be sure that given 3 variable does not retain some object for 2 longer than really needed you can easily 1 destroy this link by assigning null
to that variable.
Actually your example is somewhat tricky. Was 54 it on purpose? You seem to be masking the outer 53 val
variable with an inner lexically scoped 52 restofprogram()'s val
argument, instead of 51 actually using it. But anyway, you're asking 50 about str
so let me ignore the trickiness of 49 val
in your example just for the sake of simplicity.
My 48 guess would be that the str
variable won't 47 get collected before the restofprogram() function 46 finishes, even if it doesn't use it. If the 45 restofprogram() doesn't use str
and it doesn't 44 use eval()
and new Function()
then it could be safely collected but 43 I doubt it would. This would be a tricky 42 optimization for V8 probably not worth the 41 trouble. If there was no eval
and new Function()
in the language 40 then it would be much easier.
Now, it doesn't 39 have to mean that it would never get collected 38 because any event handler in a single-threaded 37 event loop should finish almost instantly. Otherwise 36 your whole process would be blocked and 35 you'd have bigger problems than one useless 34 variable in memory.
Now I wonder if you didn't 33 mean something else than what you actually 32 wrote in your example. The whole program 31 in Node is just like in the browser – it 30 just registers event callbacks that are 29 fired asynchronously later after the main 28 program body has already finished. Also 27 none of the handlers are blocking so no 26 function is actually taking any noticeable 25 time to finish. I'm not sure if I understood 24 what you actually meant in your question 23 but I hope that what I've written will be 22 helpful to understand how it all works.
Update:
After 21 reading more info in the comments on how 20 your program looks like I can say more.
If 19 your program is something like:
readfile("blah", function (str) {
var val = getvaluefromstr(str);
// do something with val
Server.start(function (request) {
// do something
});
});
Then you 18 can also write it like this:
readfile("blah", function (str) {
var val = getvaluefromstr(str);
// do something with val
Server.start(serverCallback);
});
function serverCallback(request) {
// do something
});
It will make 17 the str
go out of scope after Server.start() is 16 called and will eventually get collected. Also, it 15 will make your indentation more manageable 14 which is not to be underestimated for more 13 complex programs.
As for the val
you might make 12 it a global variable in this case which 11 would greatly simplify your code. Of course 10 you don't have to, you can wrestle with 9 closures, but in this case making val
global 8 or making it live in an outer scope common 7 for both the readfile callback and for the 6 serverCallback function seems like the most 5 straightforward solution.
Remember that everywhere 4 when you can use an anonymous function you 3 can also use a named function, and with 2 those you can choose in which scope do you 1 want them to live.
My guess is that str will NOT be garbage 7 collected because it can be used by restofprogram(). Yes, and 6 str should get GCed if restofprogram was 5 declared outside, except, if you do something 4 like this:
function restofprogram(val) { ... }
readfile("blah", function(str) {
var val = getvaluefromstr(str);
restofprogram(val, str);
});
Or if getvaluefromstr is declared 3 as something like this:
function getvaluefromstr(str) {
return {
orig: str,
some_funky_stuff: 23
};
}
Follow-up-question: Does 2 v8 do just plain'ol GC or does it do a combination 1 of GC and ref. counting (like python?)
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.