【问题标题】:Which way is better when we're focus on garbage collecting?当我们专注于垃圾收集时,哪种方式更好?
【发布时间】:2012-10-18 03:04:02
【问题描述】:

简单的问题,什么对垃圾收集器更好:

  • 将对象添加到数组并将 null 分配给数组单元格

this.requests[i] = new NiceClass();

this.requests[i] = null;

  • 创建简单变量并将 null 分配给该变量

var niceClass = new NiceClass();

niceClass = null;

我问是因为我想避免使用数组,因为在创建大量对象期间 - 尽管破坏了对对象的引用,因此垃圾收集器能够抓取不必要的对象 - 数组正在增长,所以我很好奇,是不是这里有必要还是只使用变量会更好?

【问题讨论】:

  • 取决于垃圾收集器。并非所有的 GC 系统都使用引用计数,这就是 = null 重置的东西派上用场的地方。
  • 也许这可能会有所帮助:stackoverflow.com/questions/1947995/…
  • 当您花费大量时间担心垃圾收集器时,我认为这表明设计存在问题。
  • ...我也不确定这两种替代方案之间的有效区别是什么。将对象的引用存储在数组中,并将对象的引用存储在变量中;为什么这有关系?参考就是参考。
  • 我正在使用一个大型的 Internet 应用程序,该应用程序具有良好的体系结构,但存在大量内存泄漏。我的任务是优化所有可以优化的东西。这就是为什么我要花很多时间担心 GC。

标签: javascript performance garbage-collection


【解决方案1】:

你忘记了几件事:

JS 的 GC 工作方式取决于实现:V8 对内存的管理非常好,而旧版本的 IE 比生锈的滤锅泄漏更多。
将变量设置为空,但是不会初始化它Null 与其他语言中的 null 不同(只需尝试在控制台中输入 typeof null)。请改用someVar = undefined。即便如此,Js 确实有一个保留的 delete 关键字,在我看来,这就是你所追求的。
总而言之:如果对象被变量或数组引用:它并不是真的问题:数组是稀疏的,所以如果你使用delete someArray[i];,那和delete someVar;之间应该没有任何区别。
注意:在全局范围内删除一个变量会always 返回 true,但如果该变量已显式声明(使用 var 关键字)或者如果它是一个函数,则它不会被删除。只能删除隐含的全局变量,因此:

var global1 = 'I cannot be deleted';
function global2()
{
    global3 = 123;//implied global
}
global4 = function()
{
    console.log('implied global function, can be deleted');
};
delete global1;//returns true
console.log(global1);//I cannot be deleted
delete global2;
global2();//shouldn't create global3, because it was deleted but:
console.log(global3);//123
delete global3;//true
console.log(global3);//undefined, was deleted
delete global4;//true
global4();//error <--- was deleted = reference error

但是:在这两种情况下,取消引用仍然在某个地方的闭包中或脚本中某处的另一个变量中引用的任何对象不会 GC 它
一般来说,JS GC 只是循环标记和刷内存:当对任何给定对象的所有引用超出范围时,它们被标记并释放内存。您对此过程没有任何真正的控制权,因此您无法真正优化您的代码。

即便如此,如果您仍想继续,并在 FF 或 Chrome 中使用时间线和分析器工具,那么请成为我的客人。但请记住:当您这样做时,您正在针对特定的 JS 引擎进行优化:V8 优化的代码可能会在 Chrome 和 Safari 中生成更清洁的内存,但就您所知,IE 可能会产生完整的哈希,或者您使用的某些技巧会导致 FF 速度变慢,而不是一开始就使用一个相当大的数组。
我想我会在这里停止这种咆哮......底线:你无法优化您无法真正控制的东西。

更新:

由于我刚刚阅读了您关于您当前遇到的内存泄漏的评论:我不认为将变量设置为 nullundefined 甚至 delete-ing 它会你有什么好处。确保(现代)GC 能够完成其工作的一个更好的方法是巧妙地使用闭包:每当函数返回时,在其范围内声明的变量都会被标记为 GC。如果返回了这些变量,或者该函数的返回值是引用这些变量的对象或另一个函数,则它们不会被 GC'ed,但不再引用的那些变量将被释放。
全局变量永远不会超出范围,因此,永远不会被 GC 处理。这就是为什么全局变量是邪恶的。如果你真的有很多 JS 代码需要优化:开始把东西放到 IIFE 中,这可以产生巨大的不同,而且只需很少的努力。

【讨论】:

  • 为什么someVar = undefined 与使用null 有什么不同? typeof null 返回的值意义不大。
  • ...而 deletenot 的变量。它仅适用于对象属性。
  • @user1689607:undefined也是所有变量都设置的值,当还没有赋值时,坚果nulltypeof null,实际上返回object,就像typeof []。使用 delete someVar 与在全局范围内使用 delete window.someVar 相同(在隐含全局变量的情况下,这很公平),因此您 正在 删除属性。总之:someVar= null; 正在设置一个变量来引用 null 对象,而 someVar = undefined 正在将一个变量设置为 no value,这稍微更有效
  • 是的,typeof null 返回"object",但这是出于历史原因(他们想为 ES6 修复它,但由于损坏而退出)。它是像undefined 这样的原始值,而不是对象。使用delete someVar 肯定与在全局中使用delete window.someVar 不同,除非您依赖于IE 错误的存在。
  • 关于 delete 关键字 - 我同意 user1689607。据此:perfectionkills.com/understanding-delete使用delete不好;
猜你喜欢
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
  • 2011-05-28
  • 2011-08-13
  • 2012-02-11
相关资源
最近更新 更多