Pass key_hash to guf_dict_find_idx to avoid re-computation
This commit is contained in:
parent
b01e087c85
commit
1e534731bb
@ -313,18 +313,18 @@ static inline size_t GUF_CAT(GUF_DICT_NAME, _probe_offset)(size_t probe_len)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t GUF_CAT(GUF_DICT_NAME, _find_idx)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key, bool *key_exists)
|
static size_t GUF_CAT(GUF_DICT_NAME, _find_idx)(GUF_DICT_NAME *ht, const GUF_DICT_KEY_T *key, GUF_DICT_HASH_T key_hash, bool *key_exists)
|
||||||
{
|
{
|
||||||
if (ht->kv_indices_cap <= 0) {
|
if (ht->kv_indices_cap <= 0) {
|
||||||
*key_exists = false;
|
*key_exists = false;
|
||||||
return SIZE_T_MAX;
|
return SIZE_T_MAX;
|
||||||
}
|
}
|
||||||
const GUF_DICT_HASH_T hash = GUF_DICT_KEY_HASH(key);
|
|
||||||
const GUF_DICT_KV_META_T hash_frag = GUF_DICT_HASH_T_GET_HASHFRAG(hash);
|
const GUF_DICT_KV_META_T key_hash_frag = GUF_DICT_HASH_T_GET_HASHFRAG(key_hash);
|
||||||
|
|
||||||
#define GUF_MOD_CAP(A) ((size_t)(A) & (size_t)(ht->kv_indices_cap - 1)) /* A % ht->kv_indices_cap (kv_indices_cap must be a power of two > 0) */
|
#define GUF_MOD_CAP(A) ((size_t)(A) & (size_t)(ht->kv_indices_cap - 1)) /* A % ht->kv_indices_cap (kv_indices_cap must be a power of two > 0) */
|
||||||
|
|
||||||
size_t idx = GUF_MOD_CAP(hash);
|
size_t idx = GUF_MOD_CAP(key_hash);
|
||||||
const size_t start_idx = idx;
|
const size_t start_idx = idx;
|
||||||
size_t first_tombstone_idx = SIZE_T_MAX;
|
size_t first_tombstone_idx = SIZE_T_MAX;
|
||||||
size_t probe_len = 0;
|
size_t probe_len = 0;
|
||||||
@ -345,11 +345,11 @@ static size_t GUF_CAT(GUF_DICT_NAME, _find_idx)(GUF_DICT_NAME *ht, const GUF_DIC
|
|||||||
first_tombstone_idx = idx;
|
first_tombstone_idx = idx;
|
||||||
}
|
}
|
||||||
goto probe;
|
goto probe;
|
||||||
} else if (hash_frag == kv_hashfrag && GUF_DICT_KEY_T_EQ(key, &(GUF_CAT(GUF_DICT_KV_DBUF, _at)(&ht->kv_elems, kv_idx)->key))) { // 3.) Key already exists.
|
} else if (key_hash_frag == kv_hashfrag && GUF_DICT_KEY_T_EQ(key, &(GUF_CAT(GUF_DICT_KV_DBUF, _at)(&ht->kv_elems, kv_idx)->key))) { // 3.) Key already exists.
|
||||||
ht->max_probelen = GUF_MAX((ptrdiff_t)probe_len, ht->max_probelen);
|
ht->max_probelen = GUF_MAX((ptrdiff_t)probe_len, ht->max_probelen);
|
||||||
*key_exists = true;
|
*key_exists = true;
|
||||||
return idx;
|
return idx;
|
||||||
} else { // 4.) Have to probe due to hash-collision/tombstone.
|
} else { // 4.) Probe because kv_idx was a tombstone or because key != kv_elems[kv_idx]
|
||||||
probe:
|
probe:
|
||||||
++probe_len;
|
++probe_len;
|
||||||
idx = GUF_MOD_CAP(start_idx + GUF_CAT(GUF_DICT_NAME, _probe_offset)(probe_len)); // NOTE: Add probe_offset to start_idx and not to idx.
|
idx = GUF_MOD_CAP(start_idx + GUF_CAT(GUF_DICT_NAME, _probe_offset)(probe_len)); // NOTE: Add probe_offset to start_idx and not to idx.
|
||||||
@ -432,10 +432,10 @@ static void GUF_CAT(GUF_DICT_NAME, _try_grow_if_necessary)(GUF_DICT_NAME *ht, gu
|
|||||||
const GUF_DICT_KV_NAME *kv = GUF_CAT(GUF_DICT_KV_DBUF, _at)(&ht->kv_elems, kv_idx);
|
const GUF_DICT_KV_NAME *kv = GUF_CAT(GUF_DICT_KV_DBUF, _at)(&ht->kv_elems, kv_idx);
|
||||||
GUF_ASSERT(kv);
|
GUF_ASSERT(kv);
|
||||||
bool key_exists = false;
|
bool key_exists = false;
|
||||||
const size_t new_idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, &kv->key, &key_exists);
|
const GUF_DICT_HASH_T key_hash = GUF_DICT_KEY_HASH(&kv->key); // TODO: might be expensive...
|
||||||
|
const size_t new_idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, &kv->key, key_hash, &key_exists);
|
||||||
GUF_ASSERT(!key_exists);
|
GUF_ASSERT(!key_exists);
|
||||||
GUF_ASSERT(new_idx < SIZE_T_MAX && new_idx < (size_t)ht->kv_indices_cap);
|
GUF_ASSERT(new_idx < SIZE_T_MAX && new_idx < (size_t)ht->kv_indices_cap);
|
||||||
const GUF_DICT_HASH_T key_hash = GUF_DICT_KEY_HASH(&kv->key); // TODO: might be expensive...
|
|
||||||
GUF_ASSERT((GUF_DICT_HASH_T_GET_HASHFRAG(key_hash) & (GUF_DICT_KV_META_T)kv_idx) == 0);
|
GUF_ASSERT((GUF_DICT_HASH_T_GET_HASHFRAG(key_hash) & (GUF_DICT_KV_META_T)kv_idx) == 0);
|
||||||
ht->kv_indices[new_idx] = GUF_DICT_HASH_T_GET_HASHFRAG(key_hash) | (GUF_DICT_KV_META_T)kv_idx;
|
ht->kv_indices[new_idx] = GUF_DICT_HASH_T_GET_HASHFRAG(key_hash) | (GUF_DICT_KV_META_T)kv_idx;
|
||||||
}
|
}
|
||||||
@ -471,7 +471,7 @@ GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _try_insert)(GUF_DICT_NAME *ht, GUF_D
|
|||||||
// 2.) Insert new key-value pair.
|
// 2.) Insert new key-value pair.
|
||||||
const GUF_DICT_HASH_T key_hash = GUF_DICT_KEY_HASH(key);
|
const GUF_DICT_HASH_T key_hash = GUF_DICT_KEY_HASH(key);
|
||||||
bool key_exists = false;
|
bool key_exists = false;
|
||||||
size_t idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, key, &key_exists);
|
size_t idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, key, key_hash, &key_exists);
|
||||||
if (key_exists) {
|
if (key_exists) {
|
||||||
guf_err_set_or_panic(err, GUF_ERR_ALREADY_EXISTS, GUF_ERR_MSG("in function dict_try_insert: Key already exists"));
|
guf_err_set_or_panic(err, GUF_ERR_ALREADY_EXISTS, GUF_ERR_MSG("in function dict_try_insert: Key already exists"));
|
||||||
return;
|
return;
|
||||||
@ -574,15 +574,16 @@ GUF_DICT_KWRDS void GUF_CAT(GUF_DICT_NAME, _insert_val_arg)(GUF_DICT_NAME *ht, G
|
|||||||
if (!key) {
|
if (!key) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
const GUF_DICT_HASH_T key_hash = GUF_DICT_KEY_HASH(key);
|
||||||
bool key_exists = false;
|
bool key_exists = false;
|
||||||
const size_t idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, key, &key_exists);
|
const size_t idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, key, key_hash, &key_exists);
|
||||||
if (!key_exists) {
|
if (!key_exists) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
GUF_ASSERT(idx != SIZE_T_MAX);
|
GUF_ASSERT(idx != SIZE_T_MAX);
|
||||||
GUF_ASSERT((ptrdiff_t)idx < ht->kv_indices_cap);
|
GUF_ASSERT((ptrdiff_t)idx < ht->kv_indices_cap);
|
||||||
const size_t kv_idx = GUF_DICT_META_GET_IDX(ht->kv_indices[idx]);
|
const size_t kv_idx = GUF_DICT_META_GET_IDX(ht->kv_indices[idx]);
|
||||||
GUF_ASSERT((ptrdiff_t)kv_idx < ht->kv_elems.size);
|
GUF_ASSERT(kv_idx <= PTRDIFF_MAX && (ptrdiff_t)kv_idx < ht->kv_elems.size);
|
||||||
return &GUF_CAT(GUF_DICT_KV_DBUF, _at)(&ht->kv_elems, kv_idx)->val;
|
return &GUF_CAT(GUF_DICT_KV_DBUF, _at)(&ht->kv_elems, kv_idx)->val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -601,7 +602,8 @@ GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _contains)(GUF_DICT_NAME *ht, const G
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool key_exists = false;
|
bool key_exists = false;
|
||||||
const size_t idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, key, &key_exists);
|
const GUF_DICT_HASH_T key_hash = GUF_DICT_KEY_HASH(key);
|
||||||
|
const size_t idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, key, key_hash, &key_exists);
|
||||||
if (key_exists) {
|
if (key_exists) {
|
||||||
GUF_ASSERT(idx != SIZE_T_MAX);
|
GUF_ASSERT(idx != SIZE_T_MAX);
|
||||||
GUF_ASSERT(!GUF_DICT_META_IS_TOMBSTONE(ht->kv_indices[idx]));
|
GUF_ASSERT(!GUF_DICT_META_IS_TOMBSTONE(ht->kv_indices[idx]));
|
||||||
@ -625,8 +627,9 @@ GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _erase)(GUF_DICT_NAME *ht, const GUF_
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GUF_DICT_HASH_T key_hash = GUF_DICT_KEY_HASH(key);
|
||||||
bool key_exists = false;
|
bool key_exists = false;
|
||||||
const size_t idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, key, &key_exists);
|
const size_t idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, key, key_hash, &key_exists);
|
||||||
if (!key_exists) {
|
if (!key_exists) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -653,8 +656,9 @@ GUF_DICT_KWRDS bool GUF_CAT(GUF_DICT_NAME, _erase)(GUF_DICT_NAME *ht, const GUF_
|
|||||||
// GUF_ASSERT(!GUF_DICT_KEY_T_EQ(key, &last_kv->key));
|
// GUF_ASSERT(!GUF_DICT_KEY_T_EQ(key, &last_kv->key));
|
||||||
|
|
||||||
// 2.) Update kv_index.
|
// 2.) Update kv_index.
|
||||||
|
const GUF_DICT_HASH_T last_key_hash = GUF_DICT_KEY_HASH(&last_kv->key);
|
||||||
bool last_key_exists = false;
|
bool last_key_exists = false;
|
||||||
const size_t last_idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, &last_kv->key, &last_key_exists);
|
const size_t last_idx = GUF_CAT(GUF_DICT_NAME, _find_idx)(ht, &last_kv->key, last_key_hash, &last_key_exists);
|
||||||
GUF_ASSERT(last_idx != idx);
|
GUF_ASSERT(last_idx != idx);
|
||||||
GUF_ASSERT(last_key_exists && (ptrdiff_t)last_idx < ht->kv_indices_cap);
|
GUF_ASSERT(last_key_exists && (ptrdiff_t)last_idx < ht->kv_indices_cap);
|
||||||
GUF_ASSERT(GUF_DICT_META_GET_IDX(ht->kv_indices[last_idx]) == (GUF_DICT_KV_META_T)(ht->kv_elems.size - 1));
|
GUF_ASSERT(GUF_DICT_META_GET_IDX(ht->kv_indices[last_idx]) == (GUF_DICT_KV_META_T)(ht->kv_elems.size - 1));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user