Cri*_*ter 38 java collections garbage-collection arraylist
清空集合(在我的情况下是一个ArrayList)与创建一个新集合(并让垃圾收集器清除旧集合)的优点和缺点是什么.
具体来说,我有一个ArrayList<Rectangle>
叫list
.当某种情况发生时,我需要清空list
并用其他内容重新填充.我是应该打电话list.clear()
还是只是制作一个新的ArrayList<Rectangle>
并让旧的垃圾收集?每种方法的优缺点是什么?
Ste*_*n C 47
回收ArrayList
(例如通过调用clear
)的好处是,您可以避免分配新的开销,以及增加它的成本...如果您没有提供良好的initialCapacity
提示.
回收利用的缺点ArrayList
包括:
该clear()
方法必须分配null
给ArrayList
s后备阵列中的每个(使用过的)插槽.
在clear()
不调整所述背衬阵列以释放存储器.因此,如果您反复填写并清除列表,它将(永久地)使用足够的内存来表示它遇到的最大列表.换句话说,您增加了内存占用.您可以通过调用trimToSize()
...创建垃圾对象等来解决这个问题.
存在可能影响性能的局部性和跨代性问题.当您反复循环使用时ArrayList
,该对象及其后备阵列可能会占用.这意味着:
列表对象和表示列表元素的对象可能位于堆的不同区域,可能会增加TLB未命中和页面流量,尤其是在GC时间.
将(年轻代)引用分配到(终端)列表的后备阵列中可能会产生写屏障开销......取决于GC实现.
对于现实生活中的应用程序,不可能准确地建模性能权衡.变量太多了.然而,"收到的智慧"是,如果你有足够的内存1和半合适的垃圾收集器,回收通常不是一个好主意.
值得注意的是,现代JVM可以非常有效地分配对象.它只需要更新到堆的"空闲"指针并写入2或3个对象标题字.内存归零由GC完成......此外,这样做的工作大致相当于将clear()
正在回收的列表中的引用置空的工作.
1 - 如果垃圾对象与非垃圾对象的比例很高,则复制收集器效率更高.如果分析这种收集器的工作方式,那么几乎所有成本都是在查找和复制可达对象时产生的.对垃圾对象唯一需要做的就是阻止零写入撤离的"从"空间准备分配新对象.
我的建议是不回收ArrayList
对象,除非你有明确的需要尽量减少(垃圾)对象的创建速度; 例如,因为它是减少(有害)GC暂停的唯一选择.
在所有条件相同的情况下,在现代Hotspot JVM上,我的理解是通过执行以下操作可以获得最佳性能:
initialSize
分配列表对象时使用准确的提示.略微过高估计略高估.das*_*ght 37
clear
当您希望减少GC上的负载时,保留容器并调用:clear()
清空数组中的所有引用,但不使该数组符合垃圾回收器的回收条件.这可能会加速未来的插入,因为内部的数组ArrayList
不需要增长.当您计划添加到容器的数据与清除的大小大致相同时,此方法尤其有用.
此外,clear
当其他对象持有您要清除的数组的引用时,可能需要使用它.
当新数据的大小可能与之前的大小不同时,释放容器并创建新容器是有意义的.当然,你可以通过clear()
联合调用来达到类似的效果 trimToSize()
.
归档时间: |
|
查看次数: |
28484 次 |
最近记录: |