and*_*dge 5 java memory optimization
我正在编写一些需要在内存中保存大量数据的"大数据"软件.我用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;
}
}
Run Code Online (Sandbox Code Playgroud)
在C++中,这个结构的大小是16个字节,这是有道理的.在Java中,我们必须是间接的.如果我创建了例如10m的这些对象并使用Runtime.totalMemory() - Runtime.freeMemory()之前和之后然后根据需要进行除法,每个结构大约需要36个字节.一个~2.4倍的内存差异非常讨厌; 当我们试图在内存中保存数亿个DataPoints时,它会变得丑陋.
我在某处看到,在Java中这样的情况下,将数据存储为数组更好 - 实质上是基于列的存储而不是基于行的存储.我想我理解这一点:基于列的方式减少了引用数量,也许JVM甚至可以智能地将整数打包成8字节的字.
我可以使用哪些其他技巧来减少内存占用的内存占用内存块,该内存块具有一个非常大的维度(数百万/数十亿的数据点)和一个非常小的维度(O(1)列数/变量)?
结果是将数据存储为4个int数组,每个条目恰好使用16个字节.经验教训:小对象在java中具有令人讨厌的比例开销.
在 Java 中查看数据结构占用了多少内存并不是那么简单。TotalMemory() 显示为 vm 分配的空间,该空间大于实际使用量。您可以尝试使用 Java 分析器来显示数据结构的空间消耗,它们非常容易设置和运行。Java 自己的VisualVM是一个方便的免费工具,它可以显示应用程序的内存行为,如果您使用它,您还将了解一些有关 Java GC 工作原理的知识。
显示性能足迹的 VisualVM 屏幕截图(图片来自http://visualvm.java.net/features.html):

如果可能的话,您还应该考虑将变量设为最终变量。它允许 Java VM 更好地优化代码(但不确定是否节省空间)。