Skip to main content

Object size

17 replies [Last post]
byhisdeeds
Offline
Joined: 2006-01-06

Please forgive me if this is the wrong forum to ask this question but I don't know where else to go. I'l be brief.

I have an object which holds about 8 integers and 8 object references and I will be creating between 100,000 and 500,000 of these.

If I want to minimise the foot print, and I have some methods in this object that do some operations on them, will I increase the size of each object by any amount. If this is so then I should include such methods in another class and pass the object reference, correct?

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
viragsaksena
Offline
Joined: 2006-01-10

A) will be much faster as the storage requirement for storing a pointer and storing the primitive are about the same. However your second approach adds a degree of indirection and additional code to deal with it and possible type casting also which will significantly slow it down. Additionally you will not get any benefits from code optimizations.

mthornton
Offline
Joined: 2003-06-10

The presence or number of methods does not change the object overhead which is typically the size of two references (3 in some older JVM). So with 8 int's and 8 references, on a 32 bit machine the overhead would be about 11% and in a 64 bit JVM about 14% overhead. Object overhead is only really significant with much smaller objects.

byhisdeeds
Offline
Joined: 2006-01-06

Thanks.

byhisdeeds
Offline
Joined: 2006-01-06

One more thing (if its not too much trouble), Which of the following would be faster or are they about the same.

A) create an object (of the size mentioned above) and place that in various variables that are used to access these object data whenever I need them in the program.

B) create a number of large nio buffers to hold the different data that I need (all int, long, double, etc) and then just store index pointers in variables within the program to reference the actual data.

I need speed and the number of these data may get large.

mthornton
Offline
Joined: 2003-06-10

Using a large nio buffer has an advantage when setting up the data as only one object need be created and it is then never moved by the garbage collector. Even better the data could be stored in a file and then mapped directly into memory.
However you pay a penalty for this in terms of flexibility and comprehensibility of the resulting code. Performance may also suffer. For the number of objects you indicate I would use regular objects and not try mapping them into a large ByteBuffer (or IntBuffer).

byhisdeeds
Offline
Joined: 2006-01-06

Thanks

byhisdeeds
Offline
Joined: 2006-01-06

Ok I have real problems now. I have an object with:

public int id = -1;
public int l = -1;
public int[] aci = new int[]{-1, -1};
public Object[] a = new Object[]{null, null, null, null};
public Object[] c = new Object[]{null, null, null, null};
public double[] pf = new double[]{0, 0, 0};
public double[] p = new double[]{0, 0, 0};
public int count = 0;
public double r = 0;
public int di = 0;
public Object db = null;
public int slice = -1;
public BitSet flags = new BitSet(20);

And this consumes 280 bytes. Now this is high because I will need to create about 1 million of these, maybe. My calculation of the actual space for the variables would be about 210 bytes.

I looked at replacing some of the object arrays with pointers to nio buffer memory, as discussed before, and a short test of access, showed a drop by a factor of 3. It took me 5 ms to iterator through 10,000 access to the objects, setting some field, while it took 16 ms to iterate through the same number of access positioning a nio buffer and putting, or getting data.

Any suggestions of what I could do to either reduce memory usage or increase access speed. I tried direct buffers and the difference was negligible.

byhisdeeds
Offline
Joined: 2006-01-06

I've done some furthur testing. The arrays seem to be very expensive in bytes. If I replace the arrays with just multiple references (i.e. a[4] with a0, a1, a2, a3) then I can reduce the size form 280 down to just under 200 bytes.

However when I add some methods to get the individual elements i.e. getElement(index), I take a performance hit.

With the straight array references it takes me about 31 ms to set a field in the object and 23 ms to get it (10000000 loops). With the get and set methods for the object whic lookup the specific field and return it (index==0?a0:index==1?a1...) it takes me 164 ms and 156ms to set and get fields respectively.

If I use a direct nio buffer it takes 293 ms and 242 ms to set and get data. I don't think I can live with that type of performnace hit.

byhisdeeds
Offline
Joined: 2006-01-06

My mistake. the get and set method using if index==0 ? a0: index==1 ? a1 : ... is just takes about twice as long as the straight methods. I was returning the a[x] before as a quick test. Guess its not so bad. Would like it faster though.

byhisdeeds
Offline
Joined: 2006-01-06

OK. For anyone who's interested. Never use arrays if you want to keep memory usage to a bare minimum. Keep them as individual variables and then inline, however many times it is required in your code use:

(i==0?var0:i==1?var1:i==2?var2:...:varn).field = ...

This is not pretty but is as fast as possible. Don't put this in another method, put it inline as many times as necessary and you will lose nothing, save space in your Java source file.

Of course if you have millions of elements in your array, this approach may not work, but if your number is small and you need every byte of memory and ounce of speed, this works.

tmnelson
Offline
Joined: 2005-11-04

Is
(i==0?var0:i==1?var1:i==2?var2:...:varn).field = ...

really faster than

switch(i) { case 0: var0.field = ...; break;
case 1: var1.field = ...; break;
case 2: var2.field = ...; break;
case 3: var3.field = ...; break; } ?

I would have expected the first to be slower, due to the (potentially) multiple comparisons involved. Guess I should compile it up and see what gets generated...

linuxhippy
Offline
Joined: 2004-01-07

> (i==0?var0:i==1?var1:i==2?var2:...:varn).field = ...
> really faster than
> switch(i) { case 0: var0.field = ...; break;

The switch should be faster, at least when the server-compiler is used.

However, all in all my advice is to not use this programming rechnique, if its really needed something is definitivly flawed. There are better ways to work arround array-overhead than this, its probably the worst thing you can do to your CPU ;)

lg Clemens

dleskov
Offline
Joined: 2003-06-27

> However, all in all my advice is to not use this
> programming rechnique, if its really needed something
> is definitivly flawed.

In this case, it is the language that is flawed

> There are better ways to work
> arround array-overhead than this, its probably the
> worst thing you can do to your CPU ;)

And the best workaround is: write in C. At least until Sun or the JCP gives us plain arrays and structs, may be some time in Java SE N+1. :)

linuxhippy
Offline
Joined: 2004-01-07

> At least
> until Sun or the JCP gives us plain arrays and
> structs, may be some time in Java SE N+1. :)
In this case its not even clear structs would have helped - maybe or maybe not, depends on the use-case.

Java was design with low language-complexity in mind, and hiding something always means tradeofs.
So yes, there are cases which can't be implemented efficient in java (but not in python or php too) - but thats maybe 0,1% of all the code out there.
Is it really an option to shoot for the 0,1% and sacrificy a lot of the language simplicity - or wouldn't it be better to just use the tools which are already there for the stuff where that really matters - like your fortran or C compiler of choice?

- Clemens

dleskov
Offline
Joined: 2003-06-27

> Java was design with low language-complexity in mind,
> and hiding something always means tradeofs.
> So yes, there are cases which can't be implemented
> efficient in java (but not in python or php too) -
> but thats maybe 0,1% of all the code out there.

Well, the code of all major operating systems probably accounts for much less than 0.1% of the source code of all applications running on them. But those are probably the most important 0.1% (or less).

Then, there is quite some high-performance code in today's games. Ever wondered why Java is not on any of the major consoles?

Then, there are many more embedded devices than PCs, and CPU/memory resources are scarce in embedded.

And the list goes on.

> Is it really an option to shoot for the 0,1% and
> sacrificy a lot of the language simplicity - or
> wouldn't it be better to just use the tools which are
> already there for the stuff where that really matters
> - like your fortran or C compiler of choice?

This is exactly the workaround I suggested.

linuxhippy
Offline
Joined: 2004-01-07

> Well, the code of all major operating systems
> probably accounts for much less than 0.1% of the
> source code of all applications running on them. But
> those are probably the most important 0.1% (or less).
>
>
> Then, there is quite some high-performance code in
> today's games. Ever wondered why Java is not on any
> of the major consoles?
>
> Then, there are many more embedded devices than PCs,
> and CPU/memory resources are scarce in embedded.

And that was exactly my point, use the tools which are best suited for a particular task.
If you try to let one tool do all and everything, it will sacrifice its strenghts.
C has been designed for developing operating systems with it, but not really large client or webapps - which is the strenght of java. Nobody really would consider writing a OS with perl or php.

mernst
Offline
Joined: 2005-02-19

Methods do not increase instance size. They only exist once.