Skip to content

Commit

Permalink
atom_table: implement rehashing
Browse files Browse the repository at this point in the history
Rehash table when count is above a certain threshold, which is computed
using capacity.

Signed-off-by: Davide Bettio <davide@uninstall.it>
  • Loading branch information
bettio committed Oct 31, 2023
1 parent 4679e3b commit 9ee7729
Showing 1 changed file with 57 additions and 2 deletions.
59 changes: 57 additions & 2 deletions src/libAtomVM/atom_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
#endif

#define DEFAULT_SIZE 8
#define CAPACITY_INCREASE 8

#define ATOM_TABLE_THRESHOLD(capacity) (capacity + (capacity >> 2))
#define ATOM_TABLE_NEW_CAPACITY(new_count) (new_count + CAPACITY_INCREASE)

struct HNode
{
Expand Down Expand Up @@ -252,8 +256,54 @@ static inline long insert_node(struct AtomTable *table, struct HNodeGroup *node_
return new_index;
}

long atom_table_ensure_atom(
struct AtomTable *table, AtomString string, enum AtomTableCopyOpt opts)
static void do_rehash(struct AtomTable *table, int new_capacity)
{
int new_size_bytes = sizeof(struct HNode *) * new_capacity;
struct HNode **new_buckets = realloc(table->buckets, new_size_bytes);
if (IS_NULL_PTR(new_buckets)) {
// Allocation failure can be ignored, the hash table will continue with the previous bucket
return;
}
memset(new_buckets, 0, new_size_bytes);
table->buckets = new_buckets;

struct HNodeGroup *group = table->first_node_group;

while (group) {
int group_count;
if (group == table->last_node_group) {
group_count = group->len - table->last_node_group_avail;
} else {
group_count = group->len;
}

for (int i = 0; i < group_count; i++) {
struct HNode *node = &group->nodes[i];
AtomString key = node->key;

unsigned long hash = sdbm_hash(key, atom_string_len(key));
unsigned long bucket_index = hash % table->capacity;

insert_node_into_bucket(table, bucket_index, node);
}

group = group->next;
}
}

static inline void maybe_rehash(struct AtomTable *table, int new_entries)
{
int new_count = table->count + new_entries;
int threshold = ATOM_TABLE_THRESHOLD(table->capacity);
if (new_count > threshold) {
return;
}

int new_capacity = ATOM_TABLE_NEW_CAPACITY(new_count);
do_rehash(table, new_capacity);
}

long atom_table_ensure_atom(struct AtomTable *table, AtomString string, enum AtomTableCopyOpt opts)
{
unsigned long hash = sdbm_hash(string, atom_string_len(string));
SMP_WRLOCK(table);
Expand Down Expand Up @@ -288,6 +338,9 @@ long atom_table_ensure_atom(
memcpy(buf, string, 1 + len);
maybe_copied = buf;
}

maybe_rehash(table, 1);

long new_index = insert_node(table, node_group, bucket_index, maybe_copied);

SMP_UNLOCK(table);
Expand Down Expand Up @@ -316,6 +369,8 @@ long atom_table_ensure_atoms(
current_atom += 1 + atom_len;
}

maybe_rehash(table, new_atoms_count);

current_atom = atoms;
int remaining_atoms = new_atoms_count;
struct HNodeGroup *node_group = table->last_node_group;
Expand Down

0 comments on commit 9ee7729

Please sign in to comment.