uthash的扩张
uthash版本 :2.0.2
作者:jafon.tian
转载请注明出处:https://blog.csdn.net/JT_Notes
什么是扩张?
uthash作为一种hash表的实现方式,必须力求随着表中元素个数的增多,表操作的性能尽量保持某个常量。为了满足要求,uthash设计了bucket结构。将元素添加到hash表的时候,先对元素key进行hash运算,然后根据计算出的hashvalue在现有bucket中进行分配。理想情况下,每个bucket中存放的元素个数为:
num_items/num_buckets+num_items%num_buckets?1:0
num_items:hash表中元素的总数
num_buckets: hash表包含的bucket个数
举个例子当前元素总数是6,bucket个数是3,那么每个bucket中理想的存放个数就是2.
如果总是是7,那么这个值就是3.
这也比较复合直观的感觉
如果不对每个bucket中能存放的元素个数做一个上限,那么随着元素总数的增多,分配到每个bucket中的元素个数也会增多,这样表操作的性能就会随着元素个数增加而变差。uthash通过宏HASH_BKT_CAPACITY_THRESH来定义bucket中元素个数的上线(后面会看到在元素分布不理想的情况下,上限会按此值的某个倍数进行调整。)
#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */
既然每个bucket能存放的个数是有上限的,那么当hash表中元素增多时,bucket的个数就有可能需要增大,我们称之为uthash扩张。
扩张什么时候发生?
前面已经提到当添加元素到hash表时,uthash扩张有可能发生。那具体的触发逻辑时什么呢?
/* add an item to a bucket */
#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \
do { \
UT_hash_bucket *_ha_head = &(head); \
_ha_head->count++; \
(addhh)->hh_next = _ha_head->hh_head; \
(addhh)->hh_prev = NULL; \
if (_ha_head->hh_head != NULL) { \
_ha_head->hh_head->hh_prev = (addhh); \
} \
_ha_head->hh_head = (addhh);