Reputation: 707736
I'm interested in whether V8 does garbage collection on the contents of individual variables within a scope or whether it only does garbage collection on the entire scope?
So, if I have this code:
function run() {
"use strict";
var someBigVar = whatever;
var cnt = 0;
var interval = setInterval(function() {
++cnt;
// do some recurring action
// interval just keeps going
// no reference to someBigVar in here
}, 1000);
someBigVar = somethingElse;
}
run();
Will V8 garbage collect someBigVar
? The closure in run()
remains alive because of the setInterval()
callback and obviously the cnt
variable is still being used so the whole scope of run()
cannot be garbage collected. But, there is no actual ongoing reference to someBigVar
.
Does V8 only garbage collect an entire scope at a time? So, the scope of run()
can't be garbage collected until the interval is stopped? Or is it smart enough to garbage collect someBigVar
because it can see that there is no code in the interval callback that actually references someBigVar
?
FYI, here's an interesting overview article on V8 garbage collection (it does not address this specific question).
Upvotes: 4
Views: 304
Reputation: 13570
Yes, it does. Only variables that are actually used inside of a closure are retained. Otherwise closure had to capture EVERYTHING that is defined in the outer scope, which could be a lot.
The only exception is if you use eval
inside of a closure. Since there is no way to statically determine, what is referenced by the argument of eval
, engines have to retain everything.
Here is a simple experiment to demonstrate this behaviour using weak module (run with --expose-gc
flag):
var weak = require('weak');
var obj = { val: 42 };
var ref = weak(obj, function() {
console.log('gc');
});
setInterval(function() {
// obj.val;
gc();
}, 100)
If there is no reference to ref
inside of the closure you will see gc
printed.
Upvotes: 2