简体   繁体   English

Java类vs数组内存大小?

[英]Java class vs array memory size?

I have to store millions of X/Y double pairs for reference in my Java program. 我必须在我的Java程序中存储数百万个X / Y双对以供参考。 I'd like to keep memory consumption as low as possible as well as the number of object references. 我想保持尽可能低的内存消耗以及对象引用的数量。 So after some thinking I decided holding the two points in a tiny double array might be a good idea, it's setup looks like so: 所以经过一番思考后,我决定将这两个点放在一个很小的双数组中可能是一个好主意,它的设置如下:

double[] node = new double[2];
node[0] = x;
node[1] = y;

I figured using the array would prevent the link between the class and my X and Y variables used in a class, as follows: 我认为使用数组会阻止类与我在类中使用的X和Y变量之间的链接,如下所示:

class Node {
     public double x, y;
}

However after reading into the way public fields in classes are stored, it dawned on me that fields may not actually be structured as pointer like structures, perhaps the JVM is simply storing these values in contiguous memory and knows how to find them without an address thus making the class representation of my point smaller than the array. 然而,在阅读了类中公共字段的存储方式后,我突然意识到字段实际上可能不是像指针一样构造结构,也许JVM只是将这些值存储在连续的内存中并且知道如何在没有地址的情况下找到它们使我的点的类表示小于数组。

So the question is, which has a smaller memory footprint? 所以问题是,内存占用量更小? And why? 为什么?

I'm particularly interested in whether or not class fields use a pointer, and thus have a 32-bit overhead, or not. 我对类字段是否使用指针特别感兴趣,因此具有32位开销。

The latter has the smaller footprint. 后者占地面积较小。

Primitive types are stored inline in the containing class. 原始类型以内联方式存储在包含类中。 So your Node requires one object header and two 64-bit slots. 因此,您的Node需要一个对象标头和两个64位插槽。 The array you specify uses one array header (>= an object header) plust two 64-bit slots. 您指定的数组使用一个数组头(> =一个对象头),最多使用两个64位槽。

If you're going to allocate 100 variables this way, then it doesn't matter so much, as it is just the header sizes which are different. 如果您要以这种方式分配100个变量,那么它并不重要,因为它只是不同的标题大小。

Caveat: all of this is somewhat speculative as you did not specify the JVM - some of these details may vary by JVM. 警告:所有这些都有些推测,因为你没有指定JVM - 其中一些细节可能因JVM而异。

I don't think your biggest problem is going to be storing the data, I think it's going to be retrieving, indexing, and manipulating it. 我不认为你最大的问题是存储数据,我认为这将是检索,索引和操作它。

However, an array, fundamentally, is the way to go. 但是,从根本上说,阵列是要走的路。 If you want to save on pointers, use a one dimensional array. 如果要保存指针,请使用一维数组。 (Someone has already said that). (有人已经说过)。

First, it must be stated that the actual space usage depends on the JVM you are using. 首先,必须说明实际的空间使用量取决于您使用的JVM。 It is strictly implementation specific. 它严格针对具体实施。 The following is for a typical mainstream JVM. 以下是典型的主流JVM。

So the question is, which has a smaller memory footprint? 所以问题是,内存占用量更小? And why? 为什么?

The 2nd version is smaller. 第二个版本更小。 An array has the overhead of the 32 bit field in the object header that holds the array's length. 数组具有对象头中32位字段的开销,该字段保存数组的长度。 In the case of a non-array object, the size is implicit in the class and does not need to be represented separately. 对于非数组对象,大小隐含在类中,不需要单独表示。

But note that this is a fixed over head per array object . 但请注意,这是每个数组对象的固定顶部。 The larger the array is, the less important the overhead is in practical terms. 阵列越大,实际开销就越不重要。 And the flipside of using a class rather than array is that indexing won't work and your code may be more complicated (and slower) as a result. 而使用类而不是数组的另一方面是索引不起作用,因此您的代码可能会更复杂(和更慢)。

A Java 2D array is actually and array of 1D arrays (etcetera), so you can apply the same analysis to arrays with higher dimensionality. Java 2D阵列实际上是一维数组(等等)的数组,因此您可以将相同的分析应用于具有更高维度的数组。 The larger the size an array has in any dimension, the less impact the overhead has. 数组在任何维度上的大小越大,开销的影响就越小。 The overhead in a 2x10 array will be less than in a 10x2 array. 2x10阵列中的开销将小于10x2阵列中的10x2 (Think it through ... 1 array of length 2 + 2 of length 10 versus 1 array of length 10 + 10 of length 2. The overhead is proportional to the number of arrays.) (认为它通过... 1个阵列长度的2 + 2长度10 相对于 1个阵列长度的10 + 10长度为2的开销是正比于阵列的数目。)

I'm particularly interested in whether or not class fields use a pointer, and thus have a 32-bit overhead, or not. 我对类字段是否使用指针特别感兴趣,因此具有32位开销。

(You are actually talking about instance fields, not class fields. These fields are not static ...) (您实际上是在谈论实例字段,而不是类字段。这些字段不是static ......)

Fields whose type is a primitive type are stored directly in the heap node of the object without any references. 类型为基本类型的字段直接存储在对象的堆节点中,而不进行任何引用。 There is no pointer overhead in this case. 在这种情况下没有指针开销。

However, if the field types were wrapper types (eg Double rather than double ) then there could be the overhead of a reference AND the overheads of the object header for the Double object. 但是,如果字段类型是包装类型(例如Double而不是double ),则可能存在引用的开销和Double对象的对象标头的开销。

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

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