什么更有效率?清空一个对象还是创建一个新对象?
“新”有多贵?我的意思是,我应该以重用同一个对象为目标,还是如果该对象“超出范围”,则与清空它相同?
例如,假设一个方法创建了一个列表:
List<Integer> list = new ArrayList<Integer>();
在该方法的末尾,该列表不再使用 - 这是否意味着不再为它分配内存,或者是否意味着有一个指向它的空指针(因为它是 '创建')。
或者,我可以向该方法发送一个“列表”,并在方法末尾将其清空: list.removeAll(list);
从内存的角度来看,这会有什么不同吗?
谢谢!
how expensive is 'new'? I mean, should I aim at reusing the same object or if the object is 'out of scope' it's the same as emptying it?
example, say a method creates a list:
List<Integer> list = new ArrayList<Integer>();
at the end of the method the list is no longer in use - does it mean that there's no memory allocated to it anymore or does it mean that there's a null pointer to it (since it was 'created').
Alternately, I can send a 'list' to the method and empty it at the end of the method with: list.removeAll(list);
will that make any difference from memory point of view?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
它是一个数组列表,因此创建一个新对象意味着分配一块内存并将其归零,再加上任何簿记开销。清除列表意味着将内存清零。这种观点会让您相信清除现有对象会更快。但是,JVM 很可能经过优化以加快内存分配速度,因此这些可能都不重要。所以只要写出清晰、可读的代码就可以了,不用担心。毕竟这是java,不是c。
its an array list, so creating a new object means allocating a slab of memory and zeroing it, plus any bookkeeping overhead. Clearing the list means zeroing the memory. This view would lead you to believe that clearing an existing object is faster. But, it's likely that the JVM is optimized to make memory allocations fast, so probably none of this matters. So just write clear, readable code, and don't worry about it. This is java after all, not c.
在方法的末尾,列表不再使用 - 这是否意味着不再有内存分配给它,或者是否意味着有一个指向它的空指针(因为它是“创建”的)。
意味着没有对它的引用,并且对象有资格进行 GC。
或者,我可以向方法发送一个“列表”,并在方法末尾将其清空:列表.removeAll(列表);从记忆的角度来看,这会有什么不同吗?
这是时间/空间之间的权衡。即使不需要创建新对象,从列表中删除元素也很耗时。
借助最新的 JVM GC 收集功能,可以在需要时创建新对象(但最好避免在循环中创建对象) )。对对象的较长引用有时会使该对象不符合 GC 的条件,如果处理不当,可能会导致内存泄漏。
at the end of the method the list is no longer in use - does it mean that there's no memory allocated to it anymore or does it mean that there's a null pointer to it (since it was 'created').
Means there are no references to it and object is eligible for GC.
Alternately, I can send a 'list' to the method and empty it at the end of the method with: list.removeAll(list); will that make any difference from memory point of view?
It's tradeoff between time/space. Removing elements from list is time consuming, even though you don't need to create new objects.
With the latest JVMs GC collection capabilities, it is ok to create new object WHEN REQUIRED (but avoiding object creation in loop is best). Longer references to an object sometimes make that object NOT eligible for GC and may cause memory leak if not handled properly.
我对java中的内存占用了解不多,但我认为清空List以重用它并不是一个好主意,因为清空List会对性能产生影响。我认为从面向对象的角度来看这也不是一个好主意,因为你应该拥有一个只有一个目的的对象。
在方法结束时,对象确实超出了范围。但这并不意味着它被垃圾收集,甚至不意味着有资格进行垃圾收集,因为其他人可能仍然引用该列表。所以基本上:如果没有对象引用该列表,那么它可能适合垃圾收集,但如果它会被垃圾收集,它仍然不确定,如果列表仍然存储在年轻一代空间中,它可以在伊甸园中空间或终身空间。
伊甸园空间是对象首先被分配的地方,当垃圾收集发生并且对象仍然存活时,它将被移动到幸存者空间。如果它仍然存活下来,它将转移到终身空间,我相信那里不会发生太多垃圾收集。但这一切都取决于一个对象的生存时间、谁引用了这个对象以及它被分配在哪里
I don't know much about memory footprints in java, but I think emptying a List to reuse it, is not such a good idea because of the performance impact of emptying the List. And I think it is also in an OO perspective not a good idea, because you should have one object with just one purpose.
At the end of a method the object is indeed out of scope. But that doesn't mean it is garbage collected or even eligible for garbage collection, because others might still reference that List. So basically: if there are no objects references to that List then it might be elegible for garbage collection, but if it will be garbage collected it still unsure, if the List is still stored in the Young Generation space it can either be in the Eden space or Tenured space.
Eden space is where objects are first allocated, when garbage collection happens and the object is still alive it will be moved to survivor space. If it still survives past that it will move on to the Tenured space, where I believe not much garbage collection happens. But all this depends how long an object lives, who refers to this object and where it is allocated
它肯定会产生一些开销。但这取决于对象的复杂程度。如果您要创建一个仅包含几个基元的对象,那么成本并不高。但是,如果您在对象内部创建对象,可能是对象的集合,如果您的构造函数正在读取某些属性文件来初始化对象的成员变量,则成本高昂!
但坦率地说,如果我们需要创建一个新对象,我们已经创建它,没有选择。如果我们不需要并且仍然在创建,那就是一种糟糕的编程。
一旦对象没有任何对它的引用,它就会超出范围,并且有资格进行垃圾回收。因此,即使它分配了一些内存,它也会在稍后的某个时刻被 GC 回收,无论何时运行,我们都不需要担心它。 (而且我们不能保证GC什么时候运行)。
最后清空集合,我认为不会让事情变得更好,因为集合中的所有单个对象都会发生同样的事情,就像集合本身发生的情况一样。他们将有资格获得 GC。
It definitely incurs some overhead. But it depends on how complex the object is. If you are creating an object with just few primitives, not that expensive. But if you are creating objects inside objects, may be collections of objects, if your constructor is reading some properties file to initialize object's member variables, EXPENSIVE!
But to be frank, if we need to create a new object, we have create it, there is no alternative. And if we don't need to and if we are still creating that is kind of bad programming.
Once the object does not have any reference to it, it becomes out of scope, and it becomes eligible for garbage collection. Hence even if it has some memory allocated, it will be reclaimed by the GC at some later point, whenever it runs, we need not worry about it. (And we cannot guarantee when will GC run).
Emptying the collection at the end, I don't think will make things any better, because the same thing will happen to all the individual objects in the collection, as what happens to the collection itself. They will become eligible for GC.
对于小型列表,
clear()
列表可能会更便宜一些。对于非常大的堆中非常大的列表的渐近情况,归结为 GC 是否可以比
clear()
for 循环更快地清零大块内存> 可以。我认为可能可以。但是,我的建议是忽略这一点,除非您有令人信服的证据(来自分析)表明您的
ArrayList
对象的周转率很高。 (仅根据您的直觉进行优化是一个坏主意。)For small lists, it is probably a bit cheaper cheaper to
clear()
the list.For the asymptotic case of really large lists in a really large heap, it boils down to whether the GC can zero a large chunk of memory faster than the
for
loop inclear()
can. And I think it probably can.However, my advice would be to ignore this unless you have convincing evidence (from profiling) that you have a high turn-over of
ArrayList
objects. (It is a bad idea to optimize based solely on your intuition.)这取决于对象的成本,包括所需的初始化和内存占用的大小。它还在很大程度上取决于应用程序的类型(应用程序还花时间在什么上)。
对于 ArrayList 的示例,已经很难给出明确的答案 - 取决于列表中有多少条目,clear() 可能非常昂贵或非常 便宜,而新的 ArrayList 的成本几乎不变。
一般经验法则是:在测量您存在性能问题之前,不要费心重用对象,然后非常确定创建对象是最重要的该问题的原因。您的应用程序中很可能存在更多有价值的优化机会。分析器将帮助您识别您花费最多时间的地方。专注于那些和更好的算法。
It depends on how costly the object is, both in terms of initialization required and how large it's memory footprint is. It also depends heavily on the kind of application (what else does the application spend time on).
For your example with the ArrayList, its already very hard to give a definite answer - depending on how many entries there are in the list, clear() can be very expensive or very cheap, while a new ArrayList has almost constant cost.
The general rule of thumb is: Don't bother with reusing objects until you have measured that you have a performance problem, and then be very sure that creating the objects is the cause of that problem. Most likely there are more rewarding optimization opportunities in your application. A profiler will help identify the places where you spend the most time. Focus on those and better algoryhtms.