Hi,
I’m trying to figure out the “right way” to be declaring a few 1d-tables for my chess-engine, in julia, such that their memory-layout is as space-efficient as possible, and (b) fixed and never changes (i.e. the gc should never shuffle around any portion or even a whole table, for whatever reason).
Specifically the requirements & specs for any one of those tables are:
-
They can be huge in size, relative to total available ram on a computer (up to ~50% of ram, as a rough estimate, in total).
-
All tables are to be allocated and initialized at startup, of the engine, and will never change in size - just data within tables might change (some will even have constant values, just for efficient lookups).
-
There will only be random-access to the tables, ever, (no looping in any regular manner). just indexed access to single entries at any given time, with no correlatation to previous indices.
…so given the above, I basically just need some kind of fixed 1d-array-structure, but with tight memory-layout (no need to grow / shrink or do other funky stuff), for being able to to access any entry with a given key
like so… entry = table[key]
.
I think this code probably summarizes, my attempts, so far, well enough…
using Formatting
using Printf
const fD = generate_formatter("%'d")
mutable struct Entry
data0::UInt64
data1::UInt16
end
function test()
nEntries = 4
table = Array{Entry,1}(undef, nEntries)
#table = Vector{Entry}(undef, nEntries) # alternative, but really same thing
for i = 1 : nEntries
table[i] = Entry(i, i) # just fill with unique dummy-data, for testing
end
entrySize = sizeof(Entry)
tableSize = sizeof(table)
@assert tableSize == nEntries * entrySize "Unexpected: sizeof(table) != nEntries*entrySize ($tableSize!=$(nEntries*entrySize))."
printfmt("size of table: {1} entries [{2} Bytes @ {3} B/entry]\n", fD(nEntries), fD(tableSize), fD(entrySize) )
return table
end
This immediately results in a failed assertion…
ERROR: AssertionError: Unexpected: sizeof(table) != nEntries*entrySize (32 != 64).
…I was expecting, the stuct to not be tightly packed, but rather padded to some multiple of the struct’s largest component (UInt64 = 8 Bytes
in this case). But why is it showing me 32 Bytes, for the Vector - are those “just” the size of the memory-pointers (64-bit, on my platform / OS)?
When removing the assertion, everything is initialized, as I had anticipated, just the sizeof(table)
doesn’t correspond to the actual size…
julia> test()
size of table: 4 entries [32 Bytes @ 16 B/entry]
4-element Vector{Entry}:
Entry(0x0000000000000001, 0x0001)
Entry(0x0000000000000002, 0x0002)
Entry(0x0000000000000003, 0x0003)
Entry(0x0000000000000004, 0x0004)
Just looking at the table-entries, clearly, the table has to have at least size >= 40 Bytes
. Is there another way, to assert the actual size of a(ny) 1d-structure, in julia? If there isn’t any easy function for querying the size of the table, can I just assume, that it is sizeof(entry) * nEntries
large (64 Bytes, in this case)? Or do I need to use some other construct, for this kind of requirement (fixed static 1d-tables)?