简体   繁体   中英

Java Performance/Memory Consumption: Class vs. Array

Out of interest: Recently, I encountered a situation in one of my Java projects where I could store some data either in a two-dimensional array or make a dedicated class for it whose instances I would put into a one-dimensional array. So I wonder whether there exist some canonical design advice on this topic in terms of performance (runtime, memory consumption)?

Without regard of design patterns (extremely simplified situation), let's say I could store data like

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

and then

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

versus

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

I somehow think that the array-based approach should be more compact (memory) and faster (access). Then again, maybe it is not, arrays are objects too and array access needs to check indexes while object member access does not.(?) The allocation of the object array would probably(?) take longer, as I need to iteratively create the instances and my code would be bigger due to the additional class.

Thus, I wonder whether the designs of the common JVMs provide advantages for one approach over the other, in terms of access speed and memory consumption?

Many thanks.

Then again, maybe it is not, arrays are objects too

That's right. So I think this approach will not buy you anything.

If you want to go down that route, you could flatten this out into a one-dimensional array (each of your "objects" then takes two slots). That would give you immediate access to all fields in all objects, without having to follow pointers, and the whole thing is just one big memory allocation: since your component type is primitive, there is just one object as far as memory allocation is concerned (the container array itself).

This is one of the motivations for people wanting to have structs and value types in Java , and similar considerations drive the development of specialized high-performance data structure libraries (that get rid of unneccessary object wrappers).

I would not worry about it, until you really have a huge datastructure, though. Only then will the overhead of the object-oriented way matter.

I somehow think that the array-based approach should be more compact (memory) and faster (access)

It won't. You can easily confirm this by using Java Management interfaces:

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);

Under measured code put new double[0] and new Object() and you will see that those allocations will require exactly the same amount of memory.

It might be that the JVM/JIT treats arrays in a special way which could make them faster to access in one way or another.

JIT do some vectorization of an array operations if for-loops . But it's more about speed of arithmetic operations rather than speed of access. Beside that, can't think about any.

The canonical advice that I've seen in this situation is that premature optimisation is the root of all evil. Following that means that you should stick with the code that is easiest to write / maintain / get past your code quality regime, and then look at optimisation if you have a measurable performance issue.

In your examples the memory consumption is similar because in the object case you have 10,000 references plus two doubles per reference, and in the 2D array case you have 10,000 references (the first dimension) to little arrays containing two doubles each. So both are one base reference plus 10,000 references plus 20,000 doubles.

A more efficient representation would be two arrays, where you'd have two base references plus 20,000 doubles.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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