Space usage of nested tuples

Are vector elements (eg tuples with three fields each) in a structure such as myList = Vector{Tuple{UInt32, UInt16, UInt16}} stored as pointers to tuples, or directly as three UInts? In other words, would myList and myMatrix (initialzed as zeros(N, 3) ) take the same amount of space on a per element basis?

Directly (“inline”) as three integers, much like an array of struct. In general, immutable “bitstype” data is stored inline in an array (or elsewhere), without pointers.

Note that a mixed-type tuple will be subject to struct padding, so there may internally be additional padding bytes between entries depending on the sizes. In the particular case of Tuple{UInt32, UInt16, UInt16} there is no padding and it requires 8 bytes per entry:

julia> a = Tuple{UInt32, UInt16, UInt16}[(3,4,5)]
1-element Vector{Tuple{UInt32, UInt16, UInt16}}:
 (0x00000003, 0x0004, 0x0005)

julia> sizeof(a)
8

but for example Tuple{UInt8, UInt64} occupies 16 bytes since the second entry is padded to an 8-byte boundary:

julia> a = Tuple{UInt8, UInt64}[(3,4)]
1-element Vector{Tuple{UInt8, UInt64}}:
 (0x03, 0x0000000000000004)

julia> sizeof(a)
16
1 Like

Yes. ismutabletype(Tuple{UInt32, UInt16, UInt16}) == false and most immutable objects are stored inline in arrays.

As for memory use, I will remark that the two aren’t quite comparable. Your tuples are heterogeneous while a Matrix must be homogeneous. But for homogeneous tuples, the two would be comparable except for possible struct padding (as discussed in the above post).

If you’re considering a layout like zeros(UInt32,N,3), you might also consider the StaticArrays.jl package for forming a Vector{SVector{3,UInt32}}. This is memory-wise identical to a Vector{NTuple{3,UInt32}} (or a zeros(UInt32,3,N) assuming no padding – note the dimensions were swapped from your question as Julia is column-major) but provides array-like behavior from the SVectors rather than tuple-like behavior.

2 Likes

Thanks!