Skip to main content

Memory Usage Question: Vector3f[] vs. float[]

5 replies [Last post]
chaose71
Offline
Joined: 2008-04-15
Points: 0

Hi,

during the development of a raycaster we stumbled over a memory usage issue we were unable to explain. In short, we compared the memory usage of a (large) Vector3f[SIZE] array (javax.vecmath.Vector3f) vs. a simple float[SIZE*3]. All tests were done with a 64 bit JRE on a 64 bit fedora 8 with 8 GB ram.

A float in java should have 4 byte (correct me if I am wrong here!), a Vector3f should take 12 byte. Since the Vector3f[] stores the references to the Vector3f objects, we exected its size to be (SIZE * (12 + reference pointer bytes)). On a 64 bit machine, I'd expect the reference pointer to have 4 byte (correct me again if I am wrong here) , so the total cost for each Vector3f[] entry should be 20 byte vs. 12 byte of 3 floats in the float array. Since we were running into serious memory problems on the 8 GB machine, I wrote a small test program, allocating some arrays to find out more. The results were:

Vector3f Array: 163 / 358MB
Float Array: 48 / 119MB

Now ... where does the overhead come from? Am I overlooking something? Since we did not know if Vector3f stores some unknown overhead, we also tried it with a MyPoint class, containing only 3 floats. The results were similiar to Vector3f:

MyPoint Array: 162 / 356MB

Any guesses?
ChaosE71

PS: The original issue is already solved, the ray caster runs fine with a float[]. However, we are still curious what causes the unexpectedly huge difference.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
chaose71
Offline
Joined: 2008-04-15
Points: 0

Here the code to test memory usag. Just comment in/out what you want to test. The System.out after each array initialization is necessary, elsehow sneaky java compiler recognizes that a big array is never used and decides to optimize it "away" ;)

[code]
import javax.vecmath.Vector3f;

public class MemTest {
private static Vector3f[] va;
private static MyPoint[] mpa;
private static float[] fa;
private static int ARRAY_SIZE = (int)Math.pow(2, 22);

private static class MyPoint {
float _a, _b, _c;

public MyPoint() {
_a = _b = _c = 0;
}
}

public static void allocate_vector3f_array() {
va = new Vector3f[ARRAY_SIZE];
for (int i=0; i va[i] = new Vector3f();
}
System.out.println("Vector3f Array ("+va.length+"): "+va[va.length/2]);
}

public static void allocate_mypoint_array() {
mpa = new MyPoint[ARRAY_SIZE];
for (int i=0; i mpa[i] = new MyPoint();
}
System.out.println("MyPoint Array ("+mpa.length+"): "+mpa[mpa.length/2]);
}

public static void allocate_float_array() {
fa = new float[3*ARRAY_SIZE];
for (int i=0; i fa[i] = 0;
}
System.out.println("Float Array ("+fa.length+"): "+fa[fa.length/2]);
}

/**
* @param args
*/
public static void main(String[] args) {
// allocate_vector3f_array();
// allocate_mypoint_array();
allocate_float_array();

System.gc();
System.out.println((Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/(1024*1024)
+" / "+Runtime.getRuntime().totalMemory()/(1024*1024)+"MB ");

}

}
[/code]

peter__lawrey
Offline
Joined: 2005-11-01
Points: 0

> Hi,
> A float in java should have 4 byte (correct me if I am wrong here!)
True.
> a Vector3f should take 12 byte.
Plus the ovhead of each object, about 16 bytes on a 64-bit JVM.
> On a 64 bit machine, I'd expect the reference pointer to have 4 byte
4 bytes is 32-bit, I think you meant to say that 64-bit is 8 bytes.
> so the total cost for each Vector3f[] entry should be 20 byte vs. 12 byte of 3 floats in the float array.
I would expect about 12 + 16 + 8 = 36 bytes per Vector3f
> Vector3f Array: [b]163[/b] / 358MB
> Float Array: [b]48[/b] / 119MB
Assuming you have created about 10 million so the size per object is about 36 bytes.
> Now ... where does the overhead come from?
You are creating objects, not C-structs.

chaose71
Offline
Joined: 2008-04-15
Points: 0

Hello Peter,

>> On a 64 bit machine, I'd expect the reference pointer to have 4 byte
> 4 bytes is 32-bit, I think you meant to say that 64-bit is 8 bytes.
You are of course right!

16 byte object overhead was the number I was missing; that pretty much explains it. I was expecting some overhead, just did not think the numbers would differ that much. But after doing some math, its pretty obvious.

Thanks for the insight!
ChaosE71

PS: I should have posted the test code before to avoid misunderstandings. The post was the last thing I did before weekend ...

ijuma
Offline
Joined: 2005-10-19
Points: 0

A Vector3f is an object so it has quite a bit of space overhead. The following blog talks about some of the overhead in the context of primitive wrapper classes:

http://blogs.sun.com/jrose/entry/fixnums_in_the_vm

Hope it helps,
Ismael

chaose71
Offline
Joined: 2008-04-15
Points: 0

Thank you Ismael, I will look into that blog!
ChaosE71