Skip to content

Commit

Permalink
tree_data OPTIMIZE optimize creation of children htable
Browse files Browse the repository at this point in the history
Here, we know the number of children that will be added in the hash
table, so create the hash table with the correct number of elements to
avoid automatic resizes.

Signed-off-by: Olivier Matz <[email protected]>
  • Loading branch information
olivier-matz-6wind authored and michalvasko committed Oct 4, 2023
1 parent 78e96d8 commit c0feb68
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 26 deletions.
35 changes: 21 additions & 14 deletions src/hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ lyht_init_hlists_and_records(struct ly_ht *ht)
LY_CHECK_ERR_RET(!ht->recs, LOGMEM(NULL), LY_EMEM);
for (i = 0; i < ht->size; i++) {
rec = lyht_get_rec(ht->recs, ht->rec_size, i);
if (i != ht->size)
if (i != ht->size) {
rec->next = i + 1;
else
} else {
rec->next = LYHT_NO_RECORD;
}
}

ht->hlists = malloc(sizeof(ht->hlists[0]) * ht->size);
Expand Down Expand Up @@ -164,8 +165,9 @@ lyht_free(struct ly_ht *ht, void (*val_free)(void *val_p))
}

if (val_free) {
LYHT_ITER_ALL_RECS(ht, hlist_idx, rec_idx, rec)
LYHT_ITER_ALL_RECS(ht, hlist_idx, rec_idx, rec) {
val_free(&rec->val);
}
}
free(ht->hlists);
free(ht->recs);
Expand Down Expand Up @@ -216,14 +218,15 @@ lyht_resize(struct ly_ht *ht, int operation, int check)
/* add all the old records into the new records array */
for (i = 0; i < old_size; i++) {
for (rec_idx = old_hlists[i].first, rec = lyht_get_rec(old_recs, ht->rec_size, rec_idx);
rec_idx != LYHT_NO_RECORD;
rec_idx = rec->next, rec = lyht_get_rec(old_recs, ht->rec_size, rec_idx)) {
rec_idx != LYHT_NO_RECORD;
rec_idx = rec->next, rec = lyht_get_rec(old_recs, ht->rec_size, rec_idx)) {
LY_ERR ret;

if (check)
if (check) {
ret = lyht_insert(ht, rec->val, rec->hash, NULL);
else
} else {
ret = lyht_insert_no_check(ht, rec->val, rec->hash, NULL);
}

assert(!ret);
(void)ret;
Expand Down Expand Up @@ -311,8 +314,8 @@ lyht_find_next_with_collision_cb(struct ly_ht *ht, void *val_p, uint32_t hash,
}

for (rec_idx = rec->next, rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx);
rec_idx != LYHT_NO_RECORD;
rec_idx = rec->next, rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx)) {
rec_idx != LYHT_NO_RECORD;
rec_idx = rec->next, rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx)) {

if (rec->hash != hash) {
continue;
Expand Down Expand Up @@ -442,24 +445,27 @@ lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_va
uint32_t rec_idx;

LY_CHECK_ERR_RET(lyht_find_rec(ht, val_p, hash, 1, NULL, NULL, &found_rec),
LOGARG(NULL, hash), LY_ENOTFOUND); /* hash not found */
LOGARG(NULL, hash), LY_ENOTFOUND); /* hash not found */

prev_rec_idx = LYHT_NO_RECORD;
LYHT_ITER_HLIST_RECS(ht, hlist_idx, rec_idx, rec) {
if (rec == found_rec)
if (rec == found_rec) {
break;
}
prev_rec_idx = rec_idx;
}

if (prev_rec_idx == LYHT_NO_RECORD) {
ht->hlists[hlist_idx].first = rec->next;
if (rec->next == LYHT_NO_RECORD)
if (rec->next == LYHT_NO_RECORD) {
ht->hlists[hlist_idx].last = LYHT_NO_RECORD;
}
} else {
prev_rec = lyht_get_rec(ht->recs, ht->rec_size, prev_rec_idx);
prev_rec->next = rec->next;
if (rec->next == LYHT_NO_RECORD)
if (rec->next == LYHT_NO_RECORD) {
ht->hlists[hlist_idx].last = prev_rec_idx;
}
}

rec->next = ht->first_free_rec;
Expand Down Expand Up @@ -495,8 +501,9 @@ lyht_remove(struct ly_ht *ht, void *val_p, uint32_t hash)
LIBYANG_API_DEF uint32_t
lyht_get_fixed_size(uint32_t item_count)
{
if (item_count == 0)
if (item_count == 0) {
return 1;
}

/* return next power of 2 (greater or equal) */
item_count--;
Expand Down
3 changes: 1 addition & 2 deletions src/tree_data_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,7 @@ lyd_insert_hash(struct lyd_node *node)
}
}
if (u >= LYD_HT_MIN_ITEMS) {
/* create hash table, insert all the children */
node->parent->children_ht = lyht_new(1, sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1);
node->parent->children_ht = lyht_new(lyht_get_fixed_size(u), sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1);
LY_LIST_FOR(node->parent->child, iter) {
if (iter->schema) {
LY_CHECK_RET(lyd_insert_hash_add(node->parent->children_ht, iter, 1));
Expand Down
25 changes: 15 additions & 10 deletions tests/utests/basic/test_hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,18 @@ test_ht_collisions(void **UNUSED(state))

/* check all records */
for (i = 0; i < 8; ++i) {
if (i == 2)
if (i == 2) {
assert_int_not_equal(UINT32_MAX, ht->hlists[i].first);
else
} else {
assert_int_equal(UINT32_MAX, ht->hlists[i].first);
}
}
for (i = 0; i < 8; ++i) {
if (i >= 2 && i < 6)
if ((i >= 2) && (i < 6)) {
assert_int_equal(LY_SUCCESS, lyht_find(ht, &i, 2, NULL));
else
} else {
assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, 2, NULL));
}
}
rec_idx = ht->hlists[2].first;
count = 0;
Expand All @@ -202,16 +204,18 @@ test_ht_collisions(void **UNUSED(state))

/* check all records */
for (i = 0; i < 8; ++i) {
if (i == 2)
if (i == 2) {
assert_int_not_equal(UINT32_MAX, ht->hlists[i].first);
else
} else {
assert_int_equal(UINT32_MAX, ht->hlists[i].first);
}
}
for (i = 0; i < 8; ++i) {
if (i == 3 || i == 5)
if ((i == 3) || (i == 5)) {
assert_int_equal(LY_SUCCESS, lyht_find(ht, &i, 2, NULL));
else
} else {
assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, 2, NULL));
}
}
rec_idx = ht->hlists[2].first;
count = 0;
Expand All @@ -224,10 +228,11 @@ test_ht_collisions(void **UNUSED(state))
assert_int_equal(count, 2);

for (i = 0; i < 8; ++i) {
if (i == 3 || i == 5)
if ((i == 3) || (i == 5)) {
assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_SUCCESS);
else
} else {
assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_ENOTFOUND);
}
}

i = 3;
Expand Down

0 comments on commit c0feb68

Please sign in to comment.