DPDK 自身有一套哈希表的实现,在 rte_hash.h 和 rte_hash.c 中。但是由于DPDK 基于 C 语言实现,因此不具备 C++ 模板和类的强大特性。在 C 语言实现的 rte_hash 中,rte_hash 结构体中用指针的形式存储了哈希函数,如果将 rte_hash 放在共享内存中,由于指针无法共享,用户需要自行计算哈希值,然后调用其他的接口将元素插入到哈希表中。总之,rte_hash 不是为了共享而设计的,所以无法满足共享的需求。
为了能够实现共享哈希表,我用 C++ 实现了一套基于 DPDK 的共享哈希表,它具有如下特性:
1. 模板化,可以容纳任意的数据类型。
2. 当哈希表满了的时候,可以自动扩容。
3. 加锁保证多进程访问共享数据的安全性。加锁采用最小粒度的加锁,以实现最高的效率。
4. 接口简单,易于使用。类似于 std::hash_map 的接口。但是对于多线程环境采取了一些特殊处理,以防止客户程序随意修改哈希表的内容。
5. 源代码遵从 GPL 开源,任何人可以随意获取代码并修改。
6. 完整代码我放在github上,参考链接:https://github.com/Jiangwlee/more-effective-dpdk-share-hashmap
以下是一段演示代码
21 int main(int argc, char **argv) { 22 int ret; 23 24 ret = rte_eal_init(argc, argv); 25 if (ret < 0) 26 rte_panic("Cannot init EAL\n"); 27 28 char name[] = "test"; 29 shm_stl::hash_map<int, int> hs(name); 30 hs.create_or_attach(); 31 hs.insert(1, 10); 32 33 int value = 0; 34 if (hs.find(1, &value)) 35 cout << "Key : 1 --> Value : " << value << endl; 36 37 int new_value = 11; 38 Add<int> add; 39 hs.update(1, new_value, add); 40 41 if (hs.find(1, &value)) 42 cout << "Key : 1 --> Value : " << value << endl; 43 44 if (hs.erase(1, &value)) 45 cout << "Erase Key : 1 --> Value " << value << " from hash_map!" << endl; 46 else 47 cout << "Erase Key : 1 fail!" << endl; 48 49 50 if (!hs.find(1, &value)) 51 cout << "Can't find Key 1!" << endl; 52 else 53 cout << "Key : 1 --> Value : " << value << endl; 54 55 //test<int, int>(); 56 return 0; }
以下是输出结果
EAL: Ask a virtual area of 0x200000 bytes EAL: Virtual area found at 0x7f4826200000 (size = 0x200000) EAL: Ask a virtual area of 0x1f800000 bytes EAL: Virtual area found at 0x7f4806800000 (size = 0x1f800000) EAL: Ask a virtual area of 0x400000 bytes EAL: Virtual area found at 0x7f4806200000 (size = 0x400000) EAL: Ask a virtual area of 0x200000 bytes EAL: Virtual area found at 0x7f4805e00000 (size = 0x200000) EAL: Requesting 256 pages of size 2MB from socket 0 EAL: TSC frequency is ~3392462 KHz EAL: Master core 1 is ready (tid=2787b840) Key : 1 --> Value : 10 Key : 1 --> Value : 21 Erase Key : 1 --> Value 21 from hash_map! Can't find Key 1!