Special-case size-1 sequential hopscotch hash table
Rather than allocate a HH_HOP_RANGE large array of buckets, allocate just 1 if the initial size is 1, then jump to HH_HOP_RANGE as soon as a second element is added to the table. There are quite a few cases where hash tables are created where there never be more than 1 (or even 0) elements in the table (e.g., a writer without readers, a reader for a keyless topic). Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
parent
0b8fd9fcc0
commit
0e888eb2ec
2 changed files with 55 additions and 29 deletions
|
@ -366,11 +366,11 @@ struct whc *whc_new (int is_transient_local, uint32_t hdepth, uint32_t tldepth)
|
|||
#if USE_EHH
|
||||
whc->seq_hash = ddsrt_ehh_new (sizeof (struct whc_seq_entry), 32, whc_seq_entry_hash, whc_seq_entry_eq);
|
||||
#else
|
||||
whc->seq_hash = ddsrt_hh_new (32, whc_node_hash, whc_node_eq);
|
||||
whc->seq_hash = ddsrt_hh_new (1, whc_node_hash, whc_node_eq);
|
||||
#endif
|
||||
|
||||
if (whc->idxdepth > 0)
|
||||
whc->idx_hash = ddsrt_hh_new (32, whc_idxnode_hash_key, whc_idxnode_eq_key);
|
||||
whc->idx_hash = ddsrt_hh_new (1, whc_idxnode_hash_key, whc_idxnode_eq_key);
|
||||
else
|
||||
whc->idx_hash = NULL;
|
||||
|
||||
|
|
|
@ -39,11 +39,17 @@ struct ddsrt_hh {
|
|||
|
||||
static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals)
|
||||
{
|
||||
uint32_t size = HH_HOP_RANGE;
|
||||
uint32_t size;
|
||||
uint32_t i;
|
||||
/* degenerate case to minimize memory use */
|
||||
if (init_size == 1) {
|
||||
size = 1;
|
||||
} else {
|
||||
size = HH_HOP_RANGE;
|
||||
while (size < init_size) {
|
||||
size *= 2;
|
||||
}
|
||||
}
|
||||
rt->hash = hash;
|
||||
rt->equals = equals;
|
||||
rt->size = size;
|
||||
|
@ -125,6 +131,25 @@ static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t
|
|||
|
||||
static void ddsrt_hh_resize (struct ddsrt_hh *rt)
|
||||
{
|
||||
if (rt->size == 1) {
|
||||
assert (rt->size == 1);
|
||||
assert (rt->buckets[0].hopinfo == 1);
|
||||
assert (rt->buckets[0].data != NULL);
|
||||
|
||||
rt->size = HH_HOP_RANGE;
|
||||
const uint32_t hash = rt->hash (rt->buckets[0].data);
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
const uint32_t start_bucket = hash & idxmask;
|
||||
|
||||
struct ddsrt_hh_bucket *newbs = ddsrt_malloc (rt->size * sizeof (*newbs));
|
||||
for (uint32_t i = 0; i < rt->size; i++) {
|
||||
newbs[i].hopinfo = 0;
|
||||
newbs[i].data = NULL;
|
||||
}
|
||||
newbs[start_bucket] = rt->buckets[0];
|
||||
ddsrt_free (rt->buckets);
|
||||
rt->buckets = newbs;
|
||||
} else {
|
||||
struct ddsrt_hh_bucket *bs1;
|
||||
uint32_t i, idxmask0, idxmask1;
|
||||
|
||||
|
@ -154,6 +179,7 @@ static void ddsrt_hh_resize (struct ddsrt_hh *rt)
|
|||
rt->size *= 2;
|
||||
rt->buckets = bs1;
|
||||
}
|
||||
}
|
||||
|
||||
int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue