注意:本文使用的代码是2018.05.07提交的master分支上的code,其具体commitID是c22fcba177bad2c755fdb6d4d52f2a799eceaf34
。
Bihash简介
Bihash(Bounded-index extensible hash),个人认为其特点可大致概括如下:
1、bihash支持8/16/24/40/48等类型,减少对于_mm_crc32_u32/16等的使用,提高效率的同时,避免引入GCC的bug;
2、bihash使用64bit Hash值,最多可以支持双层hash查找,第一层bucket查找,第二层page查找(后面具体分析其hash结构);
3、bucket大小和page大小均为2的指数倍,因此hash查找时,仅需要位与操作即可;
4、采用working_copy,bucket操作区变换前后添加内存屏障,实现线程安全,使得bihash的查找无锁,修改时仍可进行查找;
5、采用freelists减少heap的碎片化,同时提高分配效率;
6、采用cache_lru的方式,提高查找效率。
Bihash的hash值计算
Bihash计算hash值时,对key进行hash。采用clib_crc32c或者clib_xxhash算法进行计算,x86中默认为clib_crc32c。key长度为8的倍数,即为了尽量使用_mm_crc32_u64函数,避免进一步使用_mm_crc32_u32等,出现GCC bug,同时加快了计算效率。得到的hash值为64bit,其结构如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CZNqgb5s-1621438141985)(https://raw.githubusercontent.com/xftony/xftony.github.io/master/_images/2018-05-30-bihash-hash结构.jpg)]
后log2_nbuckets位用于表示所落buckets的index,中间log2_pages表示具体page的index,即bucket、page的双层hash。注意,当page级出现hash冲突的时候,该层可能被拉成线形。
Bihash数据结构简介
这里主要介绍三个数据结构,BVT (clib_bihash_value)
, BVT (clib_bihash_bucket)
,以及BVT (clib_bihash)
。其中BVT是个宏,用于将其转换为对应的bihash类型,如_8_8
,_16_8
,其中第一个数字表示key
的长度,第二个数字表示value
的长度,单位字节,所以BVT (clib_bihash_value)
阅读时可直接将其当作clib_bihash_value_8_8
。
BVT (clib_bihash_value)
为存放若干kvp的数据结构,vpp中将其记作page,默认情况每个page中存放BIHASH_KVP_PER_PAGE
(默认为4)个kvp。具体数据结构如下:
typedef struct BV (clib_bihash_value)
{ // bucket位置决定是kvp(*buckets)或者next_free(**free_list)
union
{
// 真正存放的kvp
BVT (clib_bihash_kv) kvp[BIHASH_KVP_PER_PAGE];
// 当该bucket被free后,通过next_free将释放的内存空间串联起来
struct BV (clib_bihash_value) * next_free;
};
} BVT (clib_bihash_value);
//kvp的结构体
typedef struct
{
u64 key; /**< the key */
u64 value; /**< the value */
} clib_bihash_kv_8_8_t;
BVT (clib_bihash_bucket)
为bucket的数据结构,记录该bucket的详细信息。具体数据结构如下:
typedef struct
{
union
{
struct
{ // 距离整个bihash内存头部的偏移值
u32 offset;
// bihash内是否是page是否是hash的
u8 linear_search;
// 该bucket中page数目(log2后的)
u8 log2_pages;
// bucket内kvp的数目,当为0是进行free
i16 refcnt;
};
u64 as_u64;
};
// bucket的cache,用于提高查找效率,仅对频繁查找相同内容的才有较好效果==
#if BIHASH_KVP_CACHE_SIZE > 0
u16 cache_lru;
BVT (clib_bihash_kv) cache[BIHASH_KVP_CACHE_SIZE];
#endif
} BVT (clib_bihash_bucket);
BVT (clib_bihash)
是bihash的数据结构,记录整个bihash表的全部信息,其具体数据结构如下:
typedef struct
{ // 这个目测是没有用到==, 如错,请指正^^
BVT (clib_bihash_value) * values;
// buckets指针
BVT (c