If going for a custom hashmap implementation is an option, maybe a swiss table could be useful here.
(Disclaimer: For Go 1.24, its native map implementation went from chaining map to swiss table, so I asked Gemini to generate an equivalent in C, and even though it hallucinated things like uint66_t
, it’s quite straightforward.)
If what needs to be stored is only key and value of int32
type, then the memory usage reduces to
type :: slot_t
integer(INT32) :: key, val
end type
type :: group_t
integer(INT8) :: ctrl(8) ! stores only the rightmost 7 bits of the hash
type(slot_t) :: slots(8)
end type
type :: map_t
integer :: resident = 0, deleted = 0, ngroups = 2, capacity = 16
integer :: grow_threshold, shrink_threshold, compact_threshold
type(group_t), allocatable :: groups(:)
end type
So that’s 9 bytes per slot —plus some compiler-specific overhead?
Since there are no linked lists, recursion is out of the question, along with stack exhaustion. The heart of the swiss table implementation is in its find_slot
algorithm, so that’s the only thing in need of careful consideration.
The implementation in Go 1.24’s standard library is more complex than the one in the link above, since it relies on the runtime for AES- and SSE-related instructions.