降低Java中数据结构的内存占用

时间:2017-09-21 18:25:07

标签: java memory-management data-structures

我正在开发一种存储数据样本的内存存储解决方案。这适用于多线程趋势应用程序,该应用程序将项目不断写入存储阵列,并定期从中删除项目。它将存储最新的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 / sec数据和30点(每点7200个样本)。我运行测试1小时,通过任务管理器看到增加了大约10MB的使用量。最终每个样本大约45个字节。对于我正在存储的数据类型,这似乎相当高。有那么多Java开销还是我做得不够有效?

1 个答案:

答案 0 :(得分:3)

好吧,让我们来看看你的Sample课程:

Long timestamp;
double data;

从另一个answer开始,Long占用大约16个字节(long为8个字节,开销为8个字节。

double在Java中的内存占用量为8个字节。

Sample对象引用添加至少8个字节(它需要存储long以引用内存地址。)

因此,Sample对象本身只有32个字节。

但是,您计算的平均存储大小为每Sample 45个字节。

可能的其他原因:

  • Point个对象包含String,大约8个字节+ 2个字节*长度
  • CopyOnWriteArrayList实施的开销
  • Unfreed memory - 未使用但尚未由JVM发布的内存。

然而,最可能的原因可能是不同意的记忆。由于Java的运行方式,只有在运行垃圾收集(GC)时才会释放内存(而且无法保证强制它运行)。因为您正在使用CopyOnWriteArrayList,所以当您添加对象时,您不断在幕后创建新列表,而JVM尚未发布它们,因为GC尚未运行。

这是关于Java垃圾收集机制的一些Oracle文档的link