Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty an ArrayList or just create a new one and let the old one be garbage collected? [duplicate]

What are the advantages and disadvantages of emptying a collection (in my case its an ArrayList) vs creating a new one (and letting the garbage collector clear the old one).

Specifically, I have an ArrayList<Rectangle> called list. When a certain condition occurs, I need to empty list and refill it with other contents. Should I call list.clear() or just make a new ArrayList<Rectangle> and let the old one be garbage collected? What are the pros and cons of each approach?

like image 957
Cricketer Avatar asked Aug 22 '13 02:08

Cricketer


People also ask

How do you make an ArrayList empty in Java?

clear() method removes all of the elements from this list. The list will be empty after this call returns.

Does list clear create a new list?

Actually, it will not create a new ArrayList in memory, instead it will replace the old list.

Can you add to an empty ArrayList?

For an ArrayList , this is possible only if the random index is between 0 and yourArrayList. size() . Otherwise, you will get IndexOutOfBoundsException . This is clearly stated at javadoc of ArrayList#add(int, E) .


1 Answers

The advantage of recycling an ArrayList (e.g. by calling clear) is that you avoid the overhead of allocating a new one, and the cost of growing it ... if you didn't provide a good initialCapacity hint.

The disadvantages of recycling an ArrayList include the following:

  • The clear() method has to assign null to each (used) slot in the ArrayLists backing array.

  • The clear() does not resize the backing array to release memory. So if you repeatedly fill and clear a list, it will end up (permanently) using enough memory to represent the largest list that it encounters. In other word, you have increased the memory footprint. You can combat that by calling trimToSize(), but that creates a garbage object, etcetera1.

  • There are locality and cross-generational issues that could affect performance. When you repeatedly recycle an ArrayList, the object and its backing array are likely to be tenured. That means that:

    • The list objects and the objects representing list elements are likely to be in different areas of the heap, potentially increasing TLB misses and page traffic, especially at GC time.

    • Assignment of (young generation) references into the (tenured) list's backing array are likely to incur write barrier overheads ... depending on the GC implementation.

It is not possible to accurately model the performance trade-offs for a real-life application. There are just too many variables. However, the "received wisdom" is that recycling is NOT normally a good idea if you have plenty of memory2 and a half-decent garbage collector.

It is also worth noting that a modern JVM can allocate objects very efficiently. It merely needs to update to the heap's "free" pointer and write 2 or 3 object header words. The zeroing of memory is done by the GC ... and besides the work in doing that is roughly equivalent to the work that clear() does to null out references in the list that is being recycled.


1 - It would be better for performance to create a new ArrayList than to call clear() followed by trimToSize(...). With the latter you get both the garbage collection overheads AND the overheads of superfluous nulling.

2 - A copying collector is more efficient if the proportion of garbage objects to non-garbage objects is high. If you analyse the way that this kind of collector works, the costs are almost all incurred in finding and copying reachable objects. The only thing that needs to be done to garbage objects is to block-zero-write the evacuated "from" space ready for allocation of new objects.


My advice would be NOT to recycle ArrayList objects unless you have a demonstrable need to minimize the (garbage) object creation rate; e.g. because it is the only option you have for reducing (harmful) GC pauses.

All things being equal, on a modern Hotspot JVM my understanding is that you will get best performance by doing the following:

  • Allocating new ArrayList objects rather than recycling.
  • Use accurate initialSize hints when you allocate the list objects. It is better to slightly overestimate than slightly underestimate.
like image 145
Stephen C Avatar answered Oct 02 '22 09:10

Stephen C