Slow initialization of large array of small objects

I've stumbled upon this case today and I'm wondering what is the reason behind this huge difference in time.

The first version initializes an 5k x 5k array of raw ints:

public void initializeRaw() {
  int size = 5000;
  int[][] a = new int[size][size];
  for (int i = 0; i < size; i++)
    for (int j = 0; j < size; j++)
      a[i][j] = -1;
}

and it takes roughly 300ms on my machine. On the other hand, initializing the same array with simple 2-int structs:

public class Struct { public int x; public int y; }

public void initializeStruct() {
  int size = 5000;
  Struct[][] a = new Struct[size][size];
  for (int i = 0; i < size; i++)
    for (int j = 0; j < size; j++)
      a[i][j] = new Struct();
}

takes over 15000ms.

I would expect it to be a bit slower, after all there is more memory to allocate (10 bytes instead of 4 if I'm not mistaken), but I cannot understand why could it take 50 times longer.

Could anyone explain this? Maybe there is just a better way to to this kind of initialization in Java?

EDIT: For some comparison - the same code that uses Integer instead of int/Struct works 700ms - only two times slower.

Jon Skeet
people
quotationmark

I would expect it to be a bit slower, after all there is more memory to allocate (10 bytes instead of 4 if I'm not mistaken), but I cannot understand why could it take 50 times longer.

No, it's much worse than that. In the first case, you're creating 5001 objects. In the second case, you're creating 25,005,001 objects. Each of the Struct objects is going to take between 16 and 32 bytes, I suspect. (It will depend on various JVM details, but that's a rough guess.)

Your 5001 objects in the first case will take a total of ~100MB. The equivalent objects (the arrays) may take a total of ~200MB, if you're on a platform with 64-bit references... and then there's the other 25 million objects to allocate and initialize.

So yes, a pretty huge difference...

people

See more on this question at Stackoverflow