viper从yaml中读取配置到结构体中_vppinfrahash结构简单介绍

  • hash结构管理头及键值对结构体

/* Vector header for hash tables. */typedef struct hash_header{  /* hash结构中当前已存储d的元素个数*/  uword elts;  /*Bit 1和bit2 表是否支持动态扩容调整哈希*/  u32 flags;  /* Set if user does not want table to auto-resize when sufficiently full. */#define HASH_FLAG_NO_AUTO_GROW    (1 << 0)  /* Set if user does not want table to auto-resize when sufficiently empty. */#define HASH_FLAG_NO_AUTO_SHRINK  (1 << 1)  /* Set when hash_next is in the process of iterating through this hash table. */#define HASH_FLAG_HASH_NEXT_IN_PROGRESS (1 << 2)  /*占有sizeof(hash_pair_t) 空间大小的个数的2的次幂数:     h->log2_pair_size = max_log2(x)     比如x=8 = 2的3次方(_size = 3);      x=9 :2的3次方不够(_size=3+1)      为0时,说明当前不存储value,只存储key。*/  u32 log2_pair_size;  /* 计算散列键的函数指针。哈希函数是哈希表素数大小的模等于(vec_len (v))。*/  hash_key_sum_function_t *key_sum;  /* Special values for key_sum "function". */#define KEY_FUNC_NONE    (0)  /*< sum = key */#define KEY_FUNC_POINTER_UWORD  (1)  /*< sum = *(uword *) key */#define KEY_FUNC_POINTER_U32  (2)  /*< sum = *(u32 *) key */#define KEY_FUNC_STRING         (3)  /*< sum = string_key_sum, etc. */#define KEY_FUNC_MEM    (4)  /*  /* key比较函数,不同的key类型对比不同的比较函数 */  hash_key_equal_function_t *key_equal;  /* 用户数据的勾子函数,在mhash结构中使用Hook for user's data.  Used to parameterize sum/equal functions. */  any user;  /* Format a (k,v) pair */  format_function_t *format_pair;  /* 格式化输出函数 的参数*/  void *format_pair_arg;  /* 哈希函数获得的键值的bitmap位2层意思:   * 0是:是当前未存储数据或者当前已经存储数据但有hash冲突   * 1:当前键值对应位置已存储数据*/  uword is_user[0];} hash_t;/* 键值对结构体 */typedef struct{  /*默认key是8字节*/  uword key;  /* 数值. Length is 2^log2_pair_size - 1. */  uword value[0];} hash_pair_t;

通过上面的键值对结构,可以看出key是uword类型,最多存储8个字节。所以这里key一般存储的是key的指针。

  • hash函数内存分布

hash结构分为了3部分:hash 头结构、hash元素bitmap、hash键值对区域;

具体内存分布图如下,通过内存分布此hash是一个数组方式存储。

77d66ca08e607399875277381073fc1e.png

  • hash函数冲突解决及hash表扩容问题。

hash哈希实现必须要考虑的2个问题:哈希冲突解决方式及hash表扩容问题。

vpp 的hash在解决冲突时存在2中情况的:

  1. hash表值存储key,不记录value时。

    hash结构体中log2_pair_size= 0时,表述只存储key。 存储的是指针hash_pair_t*,变成vec_head_t结构存储。如下图所示:

    e0e9a4d23f2edc11b1eb6f2b0725ef43.png

  2. hash表存储时,

    hash结构体中log2_pair_size 非0时,存储的是hash_pair_indirect_t结构。使用alloc_len保存hash_pair_t结构数量。

       增加的2中结构体,如下:

/* 哈希间接存储结构:当log2_pair_size >0 时使用*/typedef struct{  /* pair vector */  hash_pair_t *pairs;  /* padding */  u8 pad[sizeof (uword) - sizeof (hash_pair_t *)];  /* allocated length */  uword alloc_len;}hash_pair_indirect_t;/* Direct / Indirect pair union */typedef union{  hash_pair_t direct;  hash_pair_indirect_t indirect;} hash_pair_union_t;

1e7581a2ffa43d0f57568088c8e791a3.png

  • hash结构的创建和操作函数

hash函数创建都是调用hash_create2((elts),0,(value_bytes),

              (hash_key_sum_function_t *) KEY_FUNC_NONE,

              (hash_key_equal_function_t *) KEY_FUNC_NONE,

              0,0)来实现的,只是hash函数及hash比较函数不同。

f0db746c1a6283f72316a40bfff30d25.png

ac5ee01bf9806e7025e5dfbb0b2a27c8.png

  • 总结

    hash函数底层实现也依赖于vec结构。这里需要注意hash函数是不支持多线程的。所以vpp在使用一般用来存储配置表项,都是在main核中完成的。在配置下发时,会启动同步机制将worker线程锁住。所以不存在多线程并发的问题。存储量比较小时,会选择使用hash结构。当Key的大小大于8字节时,需要额外内存(比如pool结构)保存key的内容,以便于对管理hash数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值