parallel-hashmap:并发哈希表的极致,比标准库快3倍
等你来关注!
parallel-hashmap:并发哈希表的极致,比标准库快3倍
用 C++ 开发高性能并发程序,最让人头疼的就是数据结构的效率问题,尤其是哈希表。在多线程环境下,std::unordered_map 不仅慢,还需要额外的锁来保证线程安全,简直让人抓狂。今天咱们聊点硬核的——parallel-hashmap,一个比标准库快 3 倍的并发哈希表库。
哈希表的并发问题:锁?不锁?
普通的哈希表,比如 std::unordered_map,在多线程环境下操作时,得加锁,不然数据就乱套了。锁呢,简单粗暴,但代价也大,会让性能掉到谷底。而 parallel-hashmap 的牛逼之处就在于它的设计几乎把锁的开销降到了最低,甚至在有些场景下完全不用锁。
看看下面的代码,感受下这库的基本用法:
#include “parallel_hashmap/phmap.h”
#include <iostream>
#include <thread>
#include <vector>
int main() {
// 声明一个并发哈希表
phmap::parallel_flat_hash_map<int, std::string> map;
// 多线程插入数据
std::vector<std::thread> threads;
for (int i = 0; i < 4; ++i) {
threads.emplace_back([&map, i]() {
for (int j = 0; j < 1000; ++j) {
map[i * 1000 + j] = “value_” + std::to_string(i * 1000 + j);
}
});
}
// 等待线程完成
for (auto &t : threads) {
t.join();
}
// 打印结果
std::cout << “Map size: ” << map.size() << std::endl;
return 0;
}
运行后会发现,这玩意儿不仅快,而且线程安全,数据一点儿不乱。多线程插入 4000 条数据,map.size() 会准确输出 4000。
温馨提示:parallel-hashmap 提供了多种哈希表类型,比如 parallel_flat_hash_map 和 parallel_node_hash_map。选择的时候要根据你的场景来定,前者适合性能优先的场景,后者则在动态内存管理方面表现更好。
为什么它这么快?
这库快的秘诀有两个:分区锁和缓存友好的实现。简单说,它把哈希表拆成了多个“区域”,每个区域有自己的锁,操作不同区域的数据时,线程之间互不干扰。再配合缓存友好的数据布局,极大地减少了 CPU 缓存失效的概率。
下面这个示例演示了“分区锁”的威力:
#include “parallel_hashmap/phmap.h”
#include <iostream>
#include <thread>
#include <vector>
int main() {
phmap::parallel_flat_hash_map<int, int, std::hash<int>, std::equal_to<int>,
std::allocator<std::pair<const int, int>>, 8> map;
// 默认分成 8 个锁区
map[1] = 10;
map[2] = 20;
// 查看分区数量
std::cout << “Number of submaps (locks): ” << map.subcnt() << std::endl;
return 0;
}
在这里,8 是锁区的数量,你可以根据实际应用的线程数量调整它。锁区多了,线程竞争就少了,但太多了也会浪费内存,得权衡。
小踩坑提醒: 如果你用的是动态哈希表(比如 parallel_node_hash_map),插入数据时可能会触发内部的动态扩容,虽然库已经优化了这部分逻辑,但扩容时仍然会有些性能抖动。
应用场景
parallel-hashmap 适合用在多线程、高并发的场景,比如:
Web 服务的缓存系统 :快速存取请求数据,减少锁竞争。
游戏开发 :大规模玩家数据的并发读写。
日志和监控系统 :高频日志 key 的统计和聚合。
这一切的前提是你得用对地方。如果只是单线程场景,老实用 std::unordered_map 吧,毕竟这库的多线程优化带来的额外开销在单线程下并不划算。
小结
parallel-hashmap 是个让人眼前一亮的库。既快,又省心,还免费(MIT 协议)。如果你的项目正被多线程的性能瓶颈折磨,不妨试试它,可能会让你感叹:原来并发哈希表还能这么玩!
E
N
D
往期回顾
分享
收藏
在看
点赞