Jha*_*bub 2 javascript performance garbage-collection
我在关闭部分通过addy osmani 内存高效JS阅读粉碎杂志的博客.我理解以下函数保存对largeStr的引用,GC不能声明它.
var a = function () {
var largeStr = new Array(1000000).join('x');
return function () {
return largeStr;
};
}();
Run Code Online (Sandbox Code Playgroud)
他在这里提到的解决方案没有对largeStr的引用,GC可以声称它.相反,他使用smallStr.
var a = function () {
var smallStr = 'x';
var largeStr = new Array(1000000).join('x');
return function (n) {
return smallStr;
};
}();
Run Code Online (Sandbox Code Playgroud)
我得到了Addy的观点,即没有提到大事.但是,我想知道有没有(更好的)方式,我可以拥有第一个功能的功能,并使其内存效率.
第一个函数创建largeStr并返回一个引用它的函数.因此,垃圾收集器无法释放是合乎逻辑的,largeStr因为它仍然被现在包含在a变量中的函数使用.
第二个函数没有持久的引用,largeStr因此垃圾收集器可以释放它.
听起来你问是否有办法保持对大的东西的引用,但不使用那个记忆.对此的回答是否定的.
而且,这些在技术上根本不是"泄漏".它们是合法的内存使用.
您可以通过不预先构建大字符串来获得第一个函数的功能而不占用内存.如果你根据需要构建它,那么在有人调用该函数之前它将不会消耗任何内存.这显然是执行速度和内存使用之间的直接权衡,但这是你在这里的选择.如果它是预先缓存的,那么它会消耗内存.如果它仅根据需求构建,那么在使用之前它不会占用内存.
这是基于需求的构建版本,在使用之前不会占用内存:
var a = function () {
return function () {
return new Array(1000000).join('x');
};
}();
Run Code Online (Sandbox Code Playgroud)
这不必写得太过..它也可以是这个,因为没有涉及到关闭:
var a = function() {
return new Array(1000000).join('x');
}
Run Code Online (Sandbox Code Playgroud)
这两个版本的缺点是它们每次a()调用时都会创建字符串,但优点是永远不会永久缓存任何内容.a()完成所有使用后,一切都被垃圾收集.
或者,仅在首次使用时缓存它:
var a = function () {
var largeStr;
return function () {
if (!largeStr) {
largeStr = new Array(1000000).join('x');
}
return largeStr;
};
}();
Run Code Online (Sandbox Code Playgroud)
这样做的好处是,a()在第一次调用之前不会消耗内存,后续调用a()不必重新创建大字符串,但单个largeStr在创建之后永远不会被垃圾回收.
哪种方法最好取决于您的使用模式,哪种权衡在您的设计/使用中更为重要.