繁体   English   中英

Java性能/内存消耗:类与数组

[英]Java Performance/Memory Consumption: Class vs. Array

出于兴趣:最近,我在我的一个Java项目中遇到了一种情况,我可以在二维数组中存储一些数据,或为它创建一个专用类,我将它放入一维数组中。 所以我想知道在性能(运行时,内存消耗)方面是否存在关于该主题的规范设计建议?

不考虑设计模式(非常简化的情况),假设我可以存储数据

class MyContainer {
  public double a;
  public double b;
  ...
}

接着

MyContainer[] myArray = new MyContainer[10000];
for(int i = myArray.length; (--i) >= 0;) {
  myArray[i] = new MyContainer();
}
...

double[][] myData = new double[10000][2];  
...

我不知何故认为基于阵列的方法应该更紧凑(内存)和更快(访问)。 然后,也许它不是,数组也是对象,数组访问需要检查索引,而对象成员访问不需要。(?)对象数组的分配可能(?)需要更长时间,因为我需要迭代创建由于额外的类,实例和我的代码会更大。

因此,我想知道在访问速度和内存消耗方面,通用JVM的设计是否为一种方法提供了优势?

非常感谢。

然后,也许不是,数组也是对象

那就对了。 所以我认为这种做法不会给你带来任何好处。

如果你想沿着这条路走下去,你可以把它变成一维数组(每个“对象”然后需要两个插槽)。 这将使您可以立即访问所有对象中的所有字段,而无需遵循指针,整个事情只是一个大的内存分配:因为您的组件类型是原始的,就内存分配而言,只有一个对象(容器数组本身)。

这是人们想要在Java中使用结构和值类型的动机之一,类似的考虑因素推动了专用高性能数据结构库的开发(摆脱了不必要的对象包装器)。

我不担心,直到你真的拥有庞大的数据结构。 只有这样,面向对象方式的开销才会重要。

我不知何故认为基于阵列的方法应该更紧凑(内存)和更快(访问)

它不会。 您可以使用Java Management界面轻松确认:

com.sun.management.ThreadMXBean b = (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();
long selfId = Thread.currentThread().getId();
long memoryBefore = b.getThreadAllocatedBytes(selfId);

// <-- Put measured code here

long memoryAfter = b.getThreadAllocatedBytes(selfId);
System.out.println(memoryAfter - memoryBefore);

在测量代码下放置new double[0]new Object() ,您将看到这些分配将需要完全相同的内存量。

可能是JVM / JIT以特殊方式处理数组,这可能使它们以某种方式更快地访问。

如果for循环, JIT 会对数组操作进行一些矢量化 但它更多的是算术运算的速度而不是访问速度。 除此之外,想不出任何。

我在这种情况下看到的规范建议是,过早的优化是万恶之源。 接下来意味着您应该坚持使用最容易编写/维护/通过代码质量体系的代码,然后在您遇到可衡量的性能问题时查看优化。

在您的示例中,内存消耗是类似的,因为在对象的情况下,您有10,000个引用加上每个引用的两个双精度数,而在2D数组的情况下,您有10,000个引用(第一个维度)到包含两个双精度的小数组。 所以两者都是一个基础参考加上10,000个参考加上20,000个双打。

更有效的表示形式是两个数组,其中您有两个基本引用加上20,000个双精度数。

double[] a = new double[10000];
double[] b = new double[10000];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM