I'm trying to save space in a tuple, so changed the integer size for a couple of fields.
type
Hash = int
HashIdx = int8
OrderedKeyValuePair[A, B] = tuple[
hcode: Hash, prev, next: HashIdx, key: A, val: B]
var x: OrderedKeyValuePair[int, int]
echo "hcode ", x.hcode.sizeof
echo "prev ", x.prev.sizeof
echo "next ", x.next.sizeof
echo "key ", x.key.sizeof
echo "val ", x.val.sizeof
echo "total ", x.sizeof
ms:nx jim$ ./tupsize
hcode 8
prev 4
next 4
key 8
val 8
total 32
ms:nx jim$ ./tupsize
hcode 8
prev 1
next 1
key 8
val 8
total 32
When HashIdx is int/int64, total size is 40: correct When HashIdx is int32, total size is 32: correct When HashIdx is int16 or int8, the individual item sizes show the right size but the total size is still 32.
I've verified that the tuple size does stay at 32 bytes even if int8 or int16 is used.
I saw there is a {.packed.} pragma for objects, and tried adding that before the = on OrderedKeyValuePair but it has no effect. Adding it after the = gives a syntax error.
Is there a way to make Nim not add padding to a tuple? Thanks!
Field alignment is common in C, to allow fastest access. For example a int32 is often stored at a memory address which is a multiply of 4.
Generally it is a good idea to order fields in tuples and objects by size, put the large fields at the top, the small 1 byte entities at the end. So all fields may be aligned automatically without need for padding.
Maybe you should use objects instead of tuples, then packed pragma may work. Objects generally have no overhead as long as inheritance is not involved. Tuples are sometimes useful when functions return multiple results, but generally objects are fine.
Thanks, this worked!
OrderedKeyValuePair[A, B] {.packed.} = object
hcode: Hash
key: A
val: B
prev, next: HashIdx
ms:nx jim$ ./tupsize
hcode 8
prev 1
next 1
key 8
val 8
total 26
Generally it is a good idea to order fields in tuples and objects by size
Why doesn't the compiler do that automatically?
Obviously you still need to take control of field ordering for compatibility with C structs, but that should be the exception not the rule. (In Rust, if you want explicit C-compatible field ordering you have to apply a specific 'pragma' to the declaration. I remember the Mesa language doing the same back in the '80s.)
Why doesn't the compiler do that automatically?
Because days only have 24 hours.