summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-10-12 22:33:23 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2025-10-12 22:33:23 +0300
commit4670112f63966ac6d4c1d1894341b67fee931a38 (patch)
treee4b44ef222f3246d6d39482e01a35cbf0a99dea6 /include
parent3d5360c44460022a0adc40771659f11835460859 (diff)
downloadconts-4670112f63966ac6d4c1d1894341b67fee931a38.tar.gz
conts-4670112f63966ac6d4c1d1894341b67fee931a38.zip
reduce map memory usage significantly
+ Comes at some runtime cost, unfortunately
Diffstat (limited to 'include')
-rw-r--r--include/conts/map.h56
1 files changed, 37 insertions, 19 deletions
diff --git a/include/conts/map.h b/include/conts/map.h
index e3f0b2f..6b62498 100644
--- a/include/conts/map.h
+++ b/include/conts/map.h
@@ -50,6 +50,9 @@
#ifndef CONTS_MAP_H
#define CONTS_MAP_H
+/* how many times to retry placing an element in a bucket */
+#define CONTS_MAP_PACKING 4
+
static inline size_t conts_map_generic_hash(const char *s, size_t l)
{
/* djb2 */
@@ -130,20 +133,26 @@ static inline MAP_TYPE *MAP(insert)(struct MAP_ROOT *root, MAP_KEY key, MAP_TYPE
struct MAP_BUCKET *bucket = root->buckets[b];
size_t idx = CONTS_BUCKET_IDX(hash, root->pow2, b);
- struct MAP_NODE *node = &bucket->nodes[idx];
- /* free to use this slot */
- if (!node->bucket) {
- node->bucket = bucket;
- node->hash = hash;
- node->t.data = data;
- node->t.key = key;
- root->len++;
- return &node->t.data;
+ for (size_t p = 0; p < CONTS_MAP_PACKING; ++p) {
+ size_t n = idx + p;
+ if (n >= bucket->size)
+ break;
+
+ struct MAP_NODE *node = &bucket->nodes[n];
+ /* free to use this slot */
+ if (!node->bucket) {
+ node->bucket = bucket;
+ node->hash = hash;
+ node->t.data = data;
+ node->t.key = key;
+ root->len++;
+ return &node->t.data;
+ }
+
+ /* there already exists a node like this */
+ if (node->hash == hash && MAP_CMP(node->t.key, key) == 0)
+ return &node->t.data;
}
-
- /* there already exists a node like this */
- if (node->hash == hash && MAP_CMP(node->t.key, key) == 0)
- return &node->t.data;
}
/* no bucket available, create new one */
@@ -190,14 +199,23 @@ static inline MAP_TYPE *MAP(find)(struct MAP_ROOT *root, MAP_KEY key)
struct MAP_BUCKET *bucket = root->buckets[b];
size_t idx = CONTS_BUCKET_IDX(hash, root->pow2, b);
- struct MAP_NODE *node = &bucket->nodes[idx];
- if (node->hash != hash)
- continue;
+ for (size_t p = 0; p < CONTS_MAP_PACKING; ++p) {
+ size_t n = idx + p;
+ if (n >= bucket->size)
+ break;
+
+ struct MAP_NODE *node = &bucket->nodes[n];
- if (MAP_CMP(node->t.key, key) != 0)
- continue;
+ /* note no gravestones */
- return &node->t.data;
+ if (node->hash != hash)
+ continue;
+
+ if (MAP_CMP(node->t.key, key) != 0)
+ continue;
+
+ return &node->t.data;
+ }
}
return NULL;