Hash 结构
哈希表默认是支持动态扩容的,即当哈希表存放键值对大于 3/4 哈希桶的个数时,会 2 倍扩容。 哈希冲突时,Vector 长度认为是没有限制的。
Hash 结构内存分布及结构体描述
哈希结构内存分布如下图所示:
Hash 冲突时是如何解决的
哈希冲突解决分 2 中情况(具体代码在 lookup() 函数中):
1、Key 和 Vlaue 都保存时
Hash 结构体中 log2_pair_size 不等于 0 是,存储的是 hash_pair_indirect_t 结构。使用 alloc_len 保存 hash_pair_t 结构数量。
2、只保存 Key 时。
Hash结构体中 log2_pair_size= 0, 存储的是指针 hash_pair_t*,变成 vec_head_t 结构存储
Hash函数操作:
哈希函数创建 (hash.h)
Hash 函数操作
Mhash学习
Mhash 结构及相关实现描述
Mhash 操作函数
Hash 和 Mhash 的不同
1、对 Key 的处理, Hash 结构 Key 是需要使用的自己存储的,而 Mhash 结构内部会保存 Key 内容。 2、Mhash 和 Hash 都是不支持多核操作的,在使用中需要注意加锁。 3、Mhash 底层使用的是 Hash 操作函数。
MHash使用的一些问题:
1、Mhash_free 函数存在内存泄露 对 key_tmps 内存释放是在源码中没有的;在 mhash_init 函数中是有的。
always_inline void
mhash_free (mhash_t * h)
{
if (mhash_key_vector_is_heap (h))
heap_free (h->key_vector_or_heap);
else
vec_free (h->key_vector_or_heap);
vec_free (h->key_vector_free_indices);
/*对key_tmps内存释放是在源码中没有的*/
{
int i;
for (i = 0; i < vec_len (h->key_tmps); i++)
vec_free (h->key_tmps[i]);
}
vec_free (h->key_tmps);
hash_free (h->hash);
}
2、mhash_set和mhash_unset 对key_tmps的使用
always_inline void
mhash_sanitize_hash_user (mhash_t * mh)
{
uword * hash = mh->hash;
hash_t * h = hash_header (hash);
h->user = pointer_to_uword (mh);
}
static uword mhash_set_tmp_key (mhash_t * h, void * key)
{
u8 * key_tmp;
int my_cpu = os_get_cpu_number();
vec_validate(h->key_tmps, my_cpu);
key_tmp = h->key_tmps[my_cpu];
vec_reset_length (key_tmp);
if (mhash_key_vector_is_heap (h))
{
uword is_c_string = h->n_key_bytes == MHASH_C_STRING_KEY;
if (is_c_string)
vec_add (key_tmp, key, strlen (key) + 1);
else
vec_add (key_tmp, key, vec_len (key));
}
else
vec_add (key_tmp, key, h->n_key_bytes);
h->key_tmps[my_cpu] = key_tmp;
return ~0;
}
mhash_sanitize_hash_user (h);
/*i 一直返回全FF,但是怎么去查询hash对的*/
i = mhash_set_tmp_key (h, key);
p = hash_get_pair (h->hash, i);
i = mhash_set_tmp_key (h, key);
操作是i返回的是全 F,如何来查询 Vlaue 的呢?
答案就在 Hash 函数中 mhash_key_to_mem,如果 Key 是全 F 就从 key_tmps 获取 Key。
static uword \
mhash_key_sum_##N_KEY_BYTES (hash_t * h, uword key) \
{ \
mhash_t * hv = uword_to_pointer (h->user, mhash_t *); \
return mhash_key_sum_inline (mhash_key_to_mem (hv, key), \
(N_KEY_BYTES), \
hv->hash_seed); \
} \