Just a note about your 'exported memory allocation' API: struct hamt_allocator { void *(*malloc)(const size_t size); void *(*realloc)(void *chunk, const size_t size); void (*free)(void *chunk); }; This whole thing could just be: struct hamt_allocator { void *cookie; void* (*realloc) (struct hamt_allocator* h, void* chk, const size_t size); }; With the following constraints: 1. `realloc(H, nullptr, N)` -- allocated N…
Show HN: A hash array-mapped trie implementation in C
31–40 of 59 posts
Re: Show HN: A hash array-mapped trie implementation in C
#32Just a note about your 'exported memory allocation' API: struct hamt_allocator { void *(*malloc)(const size_t size); void *(*realloc)(void *chunk, const size_t size); void (*free)(void *chunk); }; This whole thing could just be: struct hamt_allocator { void *cookie; void* (*realloc) (struct hamt_allocator* h, void* chk, const size_t size); }; With the following constraints: 1. `realloc(H, nullptr, N)` -- allocated N…
I would drop the API directly and concentrate on the algorithm. If users integrating HAMT need a different allocator situation, they can solve that problem by themselves, without a run-time indirection shim. You can help those users by providing some macros somewhere like #define hamt_malloc(ctx, x) malloc(x) and so forth, so it can be retargeted in one place. Leave an ignored context argument in place for those who…
Also, if the library calls those function so frequently that the pointer indirection would be a performance problem, then there's arguably something very wrong with the library's design.
Re: Show HN: A hash array-mapped trie implementation in C
#33Re: Show HN: A hash array-mapped trie implementation in C
#34Re: Show HN: A hash array-mapped trie implementation in C
#35Earlier quoted context omitted.
There's a limit to what can be crammed into a HN comment!
I have discovered a truly marvelous allocator pattern which this HN comment is too small to contain.
Re: Show HN: A hash array-mapped trie implementation in C
#36how does HAMTs compare with more recent designs like Swiss Tables? [1] [1] https://abseil.io/about/design/swisstables
The primary advantage of hamt is that they’re persistent, so they’re immutable with cheap update, but with efficient lookup & good cache behaviour thanks to the dense nodes and high branching factor.
Re: Show HN: A hash array-mapped trie implementation in C
#37Just a note about your 'exported memory allocation' API: struct hamt_allocator { void *(*malloc)(const size_t size); void *(*realloc)(void *chunk, const size_t size); void (*free)(void *chunk); }; This whole thing could just be: struct hamt_allocator { void *cookie; void* (*realloc) (struct hamt_allocator* h, void* chk, const size_t size); }; With the following constraints: 1. `realloc(H, nullptr, N)` -- allocated N…
Sadly, this pattern doesn't work with standard realloc() anymore. C23 makes this undefined behavior due to existing non-conforming implementations. https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2464.pdf
It never really did and it wasn't supposed to.
Re: Show HN: A hash array-mapped trie implementation in C
#38Re: Show HN: A hash array-mapped trie implementation in C
#39Are these the same as Crit-bit trees [0]? [0]: https://cr.yp.to/critbit.html Edit: I think I understand now from the design section on your page, they are both tries, but the HAMT uses the hash of the key to locate the node whereas Crit-bit uses the key itself.
Crit bit tries are also, therefore, sorted. They can be iterated in order. See also https://dotat.at/prog/qp/README.html
Re: Show HN: A hash array-mapped trie implementation in C
#40Your API is missing some of the advantages relative to hash tables though. Because it's a tree, operations like union and difference of two instances can be sublinear in the size of the instances. E.g. union can copy subtrees when the other instance has empty at the corresponding position.
You're also missing a batch construction call, create a new tree out of N key/value pairs. That's much faster than inserting one at a time because you can sort the array up front and then create the tree without any temporary nodes.
The function pointers in the interface are probably difficult for the compiler to devirtualise. Changing that in C means macros or code generators though, does some damage to ease of use.
Thanks for sharing it