我正在编写一些需要在内存中保存大量数据的“大数据”软件。我用 C++ 写了一个原型,效果很好。然而,实际的最终用户通常使用 Java 编写代码,因此他们要求我也编写一个 Java 原型。
我已经完成了关于 java 内存占用的背景阅读和一些初步测试。例如,假设我有这个对象
public class DataPoint{
int cents, time, product_id, store_id;
public DataPoint(int cents, int time, int product_id, int store_id){
this.cents = cents;
this.time = time;
this.product_id = product_id;
this.store_id = store_id;
}
}
在 C++ 中,这个结构的大小是 16 字节,这是有道理的。在 Java 中,我们必须是间接的。例如,如果我创建 10m 的这些对象并在前后使用 Runtime.totalMemory() - Runtime.freeMemory(),然后根据需要进行划分,我得到每个结构大约 36 个字节。大约 2.4 倍的内存差异非常糟糕;当我们试图在内存中保存数亿个数据点时,它会变得丑陋。
我在某处读到,在 Java 中的这种情况下,最好将数据存储为数组——本质上是基于列的存储而不是基于行的存储。我想我理解这一点:基于列的方式减少了引用的数量,也许 JVM 甚至可以智能地将 int 打包成 8 字节的单词。
我可以使用哪些其他技巧来减少本质上是一个内存块的内存占用量,该内存块具有一个非常大的维度(数百万/十亿个数据点)和一个非常小的维度(O(1) 列/变量数)?
结果将数据存储为 4 个 int 数组,每个条目正好使用 16 个字节。教训:小对象在 java 中具有令人讨厌的比例开销。