Jas*_*n S 6 java data-structures
嗯.我有一个表,这是一个我需要用Java存储的结构数组.天真的不用担心内存的方法说这样做:
public class Record {
final private int field1;
final private int field2;
final private long field3;
/* constructor & accessors here */
}
List<Record> records = new ArrayList<Record>();
Run Code Online (Sandbox Code Playgroud)
如果我最终使用大量(> 10 6)记录,偶尔访问个别记录,一次一个,我如何弄清楚前面的方法(ArrayList)如何与优化的存储成本方法进行比较:
public class OptimizedRecordStore {
final private int[] field1;
final private int[] field2;
final private long[] field3;
Record getRecord(int i) { return new Record(field1[i],field2[i],field3[i]); }
/* constructor and other accessors & methods */
}
Run Code Online (Sandbox Code Playgroud)
编辑:
在这种情况下,给出通用"在必要时进行优化"的答案是无益的,因为恕我直言,程序员应该始终意识到设计选择中不同的性能,当选择导致性能损失一个数量级时,特别是API编写者.
最初的问题非常有效,我倾向于同意第二种方法更好,因为他的具体情况.我已经编写了图像处理代码,其中每个像素需要一个数据结构,这种情况与此不太相似,除了我需要频繁随机访问每个像素.为每个像素创建一个对象的开销是巨大的.
第二个版本更糟糕.执行插入或删除时,您将调整三个数组的大小,而不是调整一个数组的大小.更重要的是,第二个版本将导致创建更多临时对象,并且它将在访问时执行.这可能导致大量垃圾(从GC的角度来看).不好.
一般来说,在考虑性能之前,您应该担心如何使用对象.所以你有一个包含三个字段或三个数组的记录.哪一个更准确地描绘了您的建模?我的意思是,当你插入或删除一个项目时,你是在做三个数组中的一个还是作为一个块的所有三个?
我怀疑是后者,在这种情况下,前者更有意义.
如果您真的关心插入/删除性能,那么可能需要使用不同的数据结构,可能是SortedSet或Map或SortedMap.
如果您有数百万条记录,第二种方法有几个优点:
getRecord),它可能不是那么作为现代服务器的JVM(如Oracle的Java 7)可以适用逃逸分析和堆栈分配,以避免临时对象的堆分配在某些情况下; 无论如何,GCing短期物品很便宜.另一方面,如果没有数百万个长期存在的对象(如第一种方法中那样)可检查的可达性(或者至少这些对象可能会使您的应用程序需要更加小心),垃圾收集器可能更容易调整GC生成大小).因此,第二种方法可能更适合GC性能.但是,要了解它是否会对实际情况产生影响,应该自己制定一个基准.因此,我经常对非常大的集合使用第二种方法.但是,当然,如果你有足够的内存而不关心序列化,第一种方法就更简单了.
请注意,第二种方法可能会对缓存行为产生负面影响。如果您想一次访问一条记录,最好不要将该记录分散在各处。
此外,您在第二种方法中赢得的唯一记忆(可能)是由于成员对齐。(并且必须分配一个单独的对象)。否则,它们的内存使用量将渐进地完全相同。IMO 由于地点原因,第一个选择要好得多
| 归档时间: |
|
| 查看次数: |
10748 次 |
| 最近记录: |