我正在开发一种存储数据样本的内存存储解决方案。这是针对多线程趋势应用程序的,该应用程序不断将项目写入存储阵列,并定期从存储阵列中删除项目。它将存储最近24小时的样本。我需要能够完整或部分地获取数据。由于这些要求,我选择使用 CopyOnWriteArrayList。
存储解决方案存储在
CopyOnWriteArrayList<Point>.
我编写了两个类来容纳数据:Point 和 Samples。
点组成:
private int ioId;
private int machineId;
private jPointType pointType; //(int)
private String subfield;
private long startTimestamp;
private long endTimestamp;
private int pruneLock;
private jTrendReqType predefType; //(int)
CopyOnWriteArrayList<Sample> dataList;
示例包括:
Long timestamp;
double data;
我目前正在使用 2/秒数据和 30 个点(每个点 7200 个样本)进行测试。我运行了 1 小时的测试,通过任务管理器看到使用量增加了约 10MB。最终每个样本大约有 45 个字节。对于我存储的数据类型来说,这似乎相当高。 Java 开销是否太大,或者我做的事情效率低下?
最佳答案
好吧,让我们看看您的Sample
类:
Long timestamp;
double data;
来自此另一个 answer ,Long
大约需要 16 个字节(long
需要 8 个字节,另外还有 8 个字节的开销。
在 Java 中,double
的内存占用为 8 个字节。
Sample
对象引用至少增加了8个字节(需要存储一个long
来引用内存地址)。
因此,Sample
对象本身就有 32 个字节长。
但是,您计算出每个示例
的平均存储大小为 45 字节。
可能还有其他原因:
Point
对象包含String
,大约为 8 字节 + 2 字节 * 长度CopyOnWriteArrayList
实现的开销- 未释放的内存 - 未使用但尚未被 JVM 释放的内存。
然而,最可能的原因可能是未释放的内存。由于 Java 的运行方式,只有在运行垃圾回收 (GC) 时才会释放内存(并且没有保证强制其运行的方法)。因为您使用的是 CopyOnWriteArrayList,所以在添加对象时会不断在幕后创建新列表,而 JVM 还没有释放它们,因为 GC 尚未运行。
这是一个link有关 Java 垃圾收集机制的一些 Oracle 文档。
关于java - 降低Java中数据结构的内存占用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46350836/