V8 是否对作用域的各个部分进行垃圾回收?
Does V8 do garbage collection on individual pieces of a scope?
我感兴趣的是 V8 是对一个范围内的单个变量的内容进行垃圾回收,还是只对整个范围进行垃圾回收?
所以,如果我有这个代码:
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();
V8 会收集垃圾 someBigVar
吗?由于 setInterval()
回调,run()
中的闭包仍然存在,显然 cnt
变量仍在使用,因此无法对 run()
的整个范围进行垃圾回收。但是,没有实际持续引用 someBigVar
。
V8 是否一次只收集整个作用域的垃圾?那么, run()
的范围在间隔停止之前不能被垃圾收集?或者它是否足够聪明地进行垃圾收集 someBigVar
因为它可以看到在实际引用 someBigVar
?
的间隔回调中没有代码
仅供参考,这里有一个 interesting overview article on V8 garbage collection(它没有解决这个具体问题)。
是的,确实如此。仅保留在闭包内部实际使用的变量。否则闭包必须捕获在外部作用域中定义的所有内容,这可能会很多。
唯一的例外是在闭包内部使用 eval
。由于无法静态确定 eval
的参数引用的内容,引擎必须保留所有内容。
这里有一个简单的实验来演示使用 weak 模块(运行 和 --expose-gc
标志)的这种行为:
var weak = require('weak');
var obj = { val: 42 };
var ref = weak(obj, function() {
console.log('gc');
});
setInterval(function() {
// obj.val;
gc();
}, 100)
如果闭包内没有对 ref
的引用,您将看到 gc
打印出来。
我感兴趣的是 V8 是对一个范围内的单个变量的内容进行垃圾回收,还是只对整个范围进行垃圾回收?
所以,如果我有这个代码:
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();
V8 会收集垃圾 someBigVar
吗?由于 setInterval()
回调,run()
中的闭包仍然存在,显然 cnt
变量仍在使用,因此无法对 run()
的整个范围进行垃圾回收。但是,没有实际持续引用 someBigVar
。
V8 是否一次只收集整个作用域的垃圾?那么, run()
的范围在间隔停止之前不能被垃圾收集?或者它是否足够聪明地进行垃圾收集 someBigVar
因为它可以看到在实际引用 someBigVar
?
仅供参考,这里有一个 interesting overview article on V8 garbage collection(它没有解决这个具体问题)。
是的,确实如此。仅保留在闭包内部实际使用的变量。否则闭包必须捕获在外部作用域中定义的所有内容,这可能会很多。
唯一的例外是在闭包内部使用 eval
。由于无法静态确定 eval
的参数引用的内容,引擎必须保留所有内容。
这里有一个简单的实验来演示使用 weak 模块(运行 和 --expose-gc
标志)的这种行为:
var weak = require('weak');
var obj = { val: 42 };
var ref = weak(obj, function() {
console.log('gc');
});
setInterval(function() {
// obj.val;
gc();
}, 100)
如果闭包内没有对 ref
的引用,您将看到 gc
打印出来。