dpdk-prog-guide阅读笔记--Hash_Library

3 篇文章 0 订阅
3 篇文章 0 订阅

1. Hash API Overview

1.1 主要配置参数

1. hash表的条目数
2. key值的字节数
3. 额外配置的flag
4. hash函数

1.2主要功能

1. 根据key值增加条目
2. 根据key值删除条目
3. 根据key值查找条目

1.3 额外功能

1. 同时提供key值和重计算的hash值增加/查找/删除条目
2. 同时提供key和data来增加/查找条目
3. 同时提供key值、重计算的hash值和data来进行操作
4. delete操作时不释放条目在hash表中的空间,在多线程场景下即使条目被删除,用户也可以继续使用
  
此外,还哈希表还支持批量查询,通过调用prefetch操作,在处理当前节点时预取下一个节点的内容,显著增加内存访问效率。  

实际使用中,与key关联的data可以是由用户管理的多个不同的表中的镜像(怀疑是指针?),也可以是直接存储在哈希表中的数据。  

示例程序中的L2/L3层(MAC层/IP层)转发示例程序定义了如何根据五元组转发基于流定义的数据包,但hash表可以在更复杂的场景下使用,并提供很多在包和流上具备高性能的操作。

2. 多进程支持

hash库可以在多进程环境下使用。只有rte_hash_set_cmp_func()函数能在单进程下使用,该函数可以设置一个自定义比较函数,但多进程环境下不支持。

3. 多线程支持

hash库支持多线程,用户在创建时通过flag指定需要的模式。在任何情况下,查找操作都是线程安全的,用户可以从多个线程同时进行查找操作。  
并发的读写操作模式由以下flag定义:  
1. RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD:允许多线程写操作,key的add、delete和表的reset操作受其他线程的写保护。只有在这种情况下,reader不受持续写保护
2. RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY:允许并发的读写操作,库用读写锁来控制并发。在writer完成更新之前,程序不需要阻止reader访问hash表
3. 除了上述两个标志外,如果还设置了事务性的内存标志RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT:读写锁将使用硬件事务性内存(如Intel® TSX,如果支持的话)来确保线程安全。如果平台支持此功能,建议加上此标记,否则软件所相关的开销会拖慢并发速度
4. RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF:无锁读写并发,并发操作不使用读写锁。对于不支持事务性内存的平台(例如ARM),建议设置这个标志。如果设置了这个标志,RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL也默认被设置
5. RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL:删除hash表条目时,不释放其内存空间。只有全部reader都停止引用该条目后,程序才能释放该条目。程序可以采用RCU机制来检查reader何时停止引用该条目

4. Extendable Bucket Functionality support

RTE_HASH_EXTRA_FLAGS_EXT_TABLE标记(默认不设置),当很小的可能出现过度hash冲突,导致某个key值未能成功add,hash表的bucket将使用链表扩展来插入这些key。这个特性是为了满足那些需要插入100%大小的hash表,且不能忍受任何插入失败情况的工作场景。  
目前,无锁并发RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF不支持可扩展bucket

5。 Implementation Details (non Extendable Bucket Case)

hash表有两个主要的table:
1. 一个bucket数组,每一个bucket都由多个条目组成,每个条目包含给定key值的签名和第二张表的index
2. 存储hash表中所有key值的数组,它的数据与每个key相关联  

hash库使用布谷鸟算法(Cuckoo Hash algorithm)解决hash冲突。对于任何key值而言,hash表中有两个可选择的bucket(主/从)来进行存储存储,所以查找时只需要检查这两个bucket即可。该库使用可配置的hash函数将key转化为4byte的哈希值。bucket的index和2byte的签名都是使用部分hash(partial-key hashing)的方式派生出来的。  

一旦确定了bucket,增加、删除、查找操作的范围就被限定到这些buckets内部的条目上。为了加速搜索逻辑,bucket中的每个条目都存储2byte的key值索引和完整的key值。因为key字节数较大时,比较整个key要比比较签名花费更多的时间。不过当签名匹配时,依然需要对比完整的key值,防止匹配错误(尽管可能性很低)

示例:  
查找条目:  
首先确认主bucket并进行key值比对,如果匹配则返回存储位置,否则确认从bucket,并进行key值比对,如果匹配则返回存储位置,否则该key对应的数据未存储在表中,返回nil。  

增加条目:  
与查找类似,先确认主从bucket,如果主bucket中有富余的空条目,则将签名存储到该条目中,key和data存储在表2中,数据在表2存储位置的index被存储在表1中。如果主bucket中没有剩余的空条目,则选择一个条目,将其存储到从bucket中,然后将目标key值存储到该条目的位置。  
使用部分密钥散列(partial-key hashing)算法计算从bucket的位置。如果从bucket中有空余条目,被驱逐的条目就被存储到该位置,否则重复上述过程直到找到空条目。所有的移动过程都只在表1中进行,这将对性能造成很大影响。  
如果进行一定次数的操作后依然未找到空条目,则认为hash表无法插入该key值(若已预设flag,则可以扩展hash表)。在使用随机key值时,hash表的利用率可以在90%以上,而不需要丢弃条目(如LRU)或再次申请内存(如扩展桶和再哈希)。

删除条目:  
与查询类似,依次在主、从bucket中查找将被删除的key值,若找到则将该条目标记为空闲条目。如果hash表被设置为"no free on delete"或是"lock free read/write concurrency",则不会free被删除的条目,需要用户在readers不再引用该位置后自己完成free操作。

6. Implementation Details (with Extendable Bucket)

当RTE_HASH_EXTRA_FLAGS_EXT_TABLE标记被设置时,hash表依然使用布谷鸟算法将key和data存储到两张表中,但当算法查找不到相应的存储位置时,key值对应的从bucket将进行扩展,新增一个被链接的bucket,然后将key值放入其中。  
查找条目时,先在主、从bucket中进行查找,若未找到,则逐个查找额外链接的bucket,若依然未找到,则说明表中没有对应的key值。  
删除操作与未设置RTE_HASH_EXTRA_FLAGS_EXT_TABLE标记时类似,唯一的区别是,删除相应的条目,出现空闲位置时,将一个额外链接的条目转存到该位置来减少额外链接的长度。

7. Entry distribution in hash table

PROG-GUID文档中分别记录了哈希表条目1K和1M时,不同存储使用率下的性能比对,存储使用率低于50%时,冲突概率不到5%;存储使用率达到95%时,冲突比例约为35%。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值