本文讨论的是使用的最受欢迎的框架之一带来的开销–我敢打赌,几乎没有应用程序不使用java.util.Collections。
本文基于以下事实:框架为例如集合的初始大小提供了默认值。 因此,我们有一个假设,即大多数人不会费心地自行管理其收藏的大小,因此最终会导致未充分利用的收藏浪费了内存。 如果是这样,我们可以实施一个解决方案,告诉人们创建半空集合的位置以及如何避免浪费内存。
测量
为了检验我们的假设,我们决定测量十三种最常见的java.util.Collection成员的用法:
- java.util.HashMap
- java.util.WeakHashMap
- java.util.IdentityHashMap
- java.util.Hashtable
- java.util.LinkedHashMap
- java.util.HashSet
- java.util.LinkedHashSet
- java.util.ArrayList
- java.util.concurrent.ArrayBlockingQueue
- java.util.Vector
- java.util.ArrayDeque
- java.util.PriorityQueue
- java.util.concurrent.ConcurrentHashMap
对于从这些类派生的所有对象,我们每30秒测量一次集合中包含的对象的数量以及集合底层数组中的空白空间的数量。 这种空空间消耗的内存量浪费了集合。 使用特殊版本的Plumbr从556个不同的实际应用程序中收集了这些数据。
结果
为了估计问题的严重程度,我们在每30秒后计算了所有收集的总浪费,并针对每个会话取了这些总计的最大值和平均值。 从下图还可以看到,大多数会话(556个中的397个)的最大摘要浪费小于1 MB,只有32个会话的最大摘要浪费超过10 MB,最大约为60 MB 。
该图的读取应类似于以下示例:共有291个应用程序浪费了大于0.1MB但小于1MB的内存。
结论
将结果与分配的堆大小进行比较,我们得出的结论是,至少在将浪费定义为未使用的堆的情况下,问题还不够大。 也使我们放弃这一方向的研究是碎片化–这种浪费通常散布在100多个不同的馆藏中,从而使优化工作更加困难且更容易出错。
这项特殊的研究没有详细说明动态增加底层阵列上的CPU开销是否足够大,这将是另一个故事。
翻译自: https://www.javacodegeeks.com/2014/01/on-java-collection-waste.html