hi,

regarding the memory consumption of a tuple containing 1 object reference, i 
believe the following to be (more) accurate:

1. the tuple Avail object:
  -1 object header @ 8 bytes (klass pointer + monitor + gc bits).
 - 3 slots in the AvailObject itself (descriptor ref, objectSlots ref, intSlots 
ref) @ 4 bytes
 * total of 24 bytes (padded)

but… we also need to take the descriptor object, integer array and object array 
into account:

2. the descriptor object:
  … are shared and globally allocated once - so not taken into account.

3. the integer array object containing 1 int (the hash)
  - 1 object header @ 8 bytes
  - 1 size slot @ 4 bytes
  - 1 int @ 4 bytes
  * total of 16 bytes *

4. the object array object containing 1 object reference
 - 1 object header @ 8 bytes
 - 1 size slot @ 4 bytes
 - 1 object reference @ 4 bytes
 * total of 16 bytes *

a total of 56 bytes on a 32 bits jvm.
 
on a 64 bit jvm, that figure is going to be obviously worse: uncompressed, 
every object header goes from 8 to 16 bytes and every object reference goes 
from 4 to 8 bytes:

1. tuple object (64 bit, uncompressed): 40 bytes
2. integer array (64 bit, uncompressed): 24 bytes
3. object array (64 bit, uncompressed): 32 bytes (padded).

a total of 96 bytes o a 64 bit jvm - uncompressed.

compressed, every object header goes from 8 to 12 bytes and every object 
reference will stay 4 bytes (if the heap stay below 4 gig).

1. tuple object (64 bit, compressed): 24 bytes
2. integer array (64 bit, compressed): 24 bytes (padded).
3. object array (64 bit, compressed): 24 bytes (padded).

a total of 72 bytes on a 64 bit jvm - compressed. 
that’s 3 times as big as a regular java object array containing one object 
reference.

i’m sure the llvm memory representation will be much better.

cheers,
- robbert

> Like all AvailObjects, a tuple has the usual Java header and two slots, one 
> for the array of AvailObjects and one for the array of ints.  An ordinary 
> tuple (not one containing, say, a character or a nybble) has one object slot 
> and one integer slot, so both arrays are necessary.  When there are zero 
> object slots or integer slots in an AvailObject, the single shared empty 
> array of objects or the single shared empty array of ints is used instead of 
> creating one especially for that AvailObject.  However, since we need one 
> slot of each for the one-element ordinary tuple (whose descriptor is an 
> ObjectTupleDescriptor), we have:
> 
>       3 object headers (AvailObject, AvailObject [], int []) @ 8 bytes each,
>       3 slots in the AvailObject itself (descriptor, objectSlots, intSlots) @ 
> 8 bytes each
>       1 slot in the int [] @ 4 bytes (to cache the tuple's hash value)
>       1 slot in the AvailObject [] @ 8 bytes (the tuple element)
> 
> So a one-element tuple takes 60 bytes.  On the other hand, the zero element 
> tuple is shared and takes no additional space per use (the slot holding it 
> would be accounted with whatever structure owns the slot).
> 
> Compressed pointers would shave it to 44 bytes.  The custom representation 
> we'll be using with LLVM will look like:
> 
>       ...before the object...
>       [tuple element #1] @ 8 bytes
>       [middle-header] @ 8 bytes
>       [int slot #1 for hash] @ 4 bytes
>       ...after the object...
> 
> = 20 bytes.

Reply via email to