【问题标题】:what's more efficient? to empty an object or create a new one?什么更有效率?清空对象或创建新对象?
【发布时间】:2012-03-08 00:31:45
【问题描述】:

“新”有多贵?我的意思是,我应该以重用同一个对象为目标,还是如果该对象“超出范围”与清空它一样?

例如,一个方法创建一个列表:

List<Integer> list = new ArrayList<Integer>(); 

在方法的末尾,列表不再使用——这是否意味着不再为其分配内存,或者是否意味着有一个空指针指向它(因为它是“创建的”)。

或者,我可以向方法发送一个“列表”,并在方法结束时将其清空:list.removeAll(list); 从内存的角度来看,这有什么不同吗?

谢谢!

【问题讨论】:

  • 我认为编写清晰易读的代码更有意义。你不应该担心java中的这种事情。
  • 在某些时候,不再使用的对象(例如超出范围)将被 JVM 自动垃圾收集。如果您愿意,您可以清理列表,但 JVM 会在某个时候为您处理它们。
  • 如果你有足够的时间来清除列表,那么你可以做到。否则是一个很大的问题。

标签: java list memory-management new-operator memory-efficient


【解决方案1】:

它是一个数组列表,因此创建一个新对象意味着分配一块内存并将其归零,以及任何簿记开销。清除列表意味着将内存归零。这种观点会让您相信清除现有对象会更快。但是,JVM 很可能已经过优化以快速分配内存,所以这些可能都不重要。因此,只需编写清晰易读的代码,不要担心。这毕竟是java,不是c。

【讨论】:

    【解决方案2】:

    在方法的末尾,列表不再使用 - 这是否意味着不再为它分配内存,或者是否意味着有一个空指针指向它(因为它是“创建”的) .

    表示没有对它的引用,并且对象符合 GC 条件。

    或者,我可以向方法发送一个“列表”,并在方法结束时将其清空:list.removeAll(list);从记忆的角度来看,这会有什么不同吗?

    这是时间/空间之间的权衡。即使您不需要创建新对象,从列表中删除元素也很耗时。

    使用最新的 JVM GC 收集功能,可以在需要时创建新对象(但最好避免在循环中创建对象)。对对象的较长引用有时会使该对象不符合 GC 条件,如果处理不当可能会导致内存泄漏。

    【讨论】:

      【解决方案3】:

      我对 java 中的内存占用了解不多,但我认为清空 List 以重用它并不是一个好主意,因为清空 List 会影响性能。而且我认为从 OO 的角度来看这也不是一个好主意,因为您应该拥有一个只有一个目的的对象。

      在方法结束时,对象确实超出了范围。但这并不意味着它被垃圾收集,甚至有资格进行垃圾收集,因为其他人可能仍然引用该列表。所以基本上:如果没有对该列表的对象引用,那么它可能适合垃圾收集,但如果它会被垃圾收集它仍然不确定,如果列表仍然存储在年轻一代空间中,它可以在伊甸园中空间或永久空间。 伊甸园空间是第一次分配对象的地方,当垃圾收集发生并且对象仍然活着时,它将被移动到幸存者空间。如果它仍然存在,它将进入 Tenured 空间,我相信不会发生太多垃圾收集。但这一切都取决于一个对象的生命周期、谁引用了这个对象以及它被分配到哪里

      【讨论】:

        【解决方案4】:

        “新”有多贵?

        这肯定会产生一些开销。但这取决于对象的复杂程度。如果您要创建一个只有几个基元的对象,那么成本不会那么高。但是如果你在对象内部创建对象,可能是对象的集合,如果你的构造函数正在读取一些属性文件来初始化对象的成员变量,那么昂贵!

        但坦率地说,如果我们需要创建一个新对象,我们已经创建它,没有替代。如果我们不需要,如果我们仍在创建,那是一种糟糕的编程。

        在方法结束时列表不再使用 - 这是否意味着 没有内存分配给它,或者这是否意味着 有一个指向它的空指针(因为它是“创建的”)。

        一旦对象没有对它的任何引用,它就会超出范围,并且有资格进行垃圾回收。因此,即使它分配了一些内存,它也会在稍后被 GC 回收,每当它运行时,我们都不必担心它。 (而且我们不能保证 GC 什么时候运行)。

        最后清空集合,我认为不会让事情变得更好,因为集合中的所有单个对象都会发生同样的事情,就像集合本身发生的事情一样。他们将有资格获得 GC。

        【讨论】:

          【解决方案5】:

          对于小型列表,clear() 列表可能会便宜一些。

          对于非常大的堆中非常大的列表的渐近情况,归结为 GC 是否可以比 clear() 中的 for 循环更快地清零一大块内存。而且我认为它可能可以。

          但是,我的建议是忽略这一点,除非您有令人信服的证据(来自分析)证明您的 ArrayList 对象的周转率很高。 (仅凭直觉进行优化是个坏主意。)

          【讨论】:

            【解决方案6】:

            这取决于对象的成本,包括所需的初始化以及它的内存占用量有多大。它还很大程度上取决于应用程序的类型(应用程序还花时间在什么方面)。

            对于您的 ArrayList 示例,已经很难给出明确的答案 - 取决于列表中有多少条目,clear() 可能非常昂贵或非常 便宜,而新的 ArrayList 成本几乎不变。

            一般的经验法则是:在您测量您有性能问题,然后非常确定创建对象是该问题的原因。您的应用程序中很可能有更多有价值的优化机会。分析器将帮助确定您花费最多时间的地方。专注于那些和更好的算法。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-02-16
              • 1970-01-01
              • 1970-01-01
              • 2019-10-21
              • 1970-01-01
              • 2017-03-23
              • 2017-10-24
              相关资源
              最近更新 更多