C++ unordered_map 性能优化

一 插入加速

unordered_map 在桶满时自动进行 rehash 操作。手动调用 rehash 函数可以手动调整 桶数量。

rehash 函数被调用时,需要注意以下几点:

  • rehash 函数可能会造成 unordered_map 的迭代器失效。如果我们在重新哈希后仍需要继续迭代 unordered_map,则需要重新获取 unordered_map 的迭代器。
  • 手动指定桶数量时,应该尽量选择一个合适的值。过小的桶数量会导致哈希冲突概率增加,从而降低 unordered_map 的性能;过大的桶数量会带来额外的空间浪费。通常,桶数量选择 2 的整数幂比选择任意数字要好。

如果对插入的性能有要求,最好事先评估需要的桶的数量,在初始化时候调用reserve()来预留足够的桶,防止后面插入时发送rehash。

二 查看冲突情况和减少冲突概率

查看桶个数、每个桶中元素个数、冲突个数:

size_t collisions = 0;
for (size_t  b = 0; b != myMap.bucket_count(); ++b)
    if (tuples.bucket_size(bucket) > 1)
        collisions += tuples.bucket_size(bucket) - 1;
std::cout << myMap.bucket_count() << "," << myMap.size() << "," << collisions << std::endl;

如果发现冲突较多,可以采用reserve()函数在初始化时增加bucket_count数量,减少冲突概率。

下图中,比较了3种情况下,插入相同的4905个不同合约(类型为std::string)为key的数据:
不reserve多次运行:
在这里插入图片描述
在这里插入图片描述
下面第1行是reserve(10000), 第2行是reserve(100000):
在这里插入图片描述

可以推测出:

  • 默认的std::string 作为key的 hash function以固定的。多次运行,在不提前reserve桶个数前提下,插入相同的一系列数据后, 桶数量和冲突数量每次运行都一样;
  • 相同的一系列数据,reserve的桶数量越大,冲突越少;

三 使用struct/class作为key

四 std::string 与 char * 作为key的对比

参考资料:

【1】https://stackoverflow.com/questions/4704521/how-to-i-count-key-collisions-when-using-boostunordered-map
【2】Swisstable:C++中比std::unordered_map更快的hash表 【https://zhuanlan.zhihu.com/p/485294786】
【3】https://deepinout.com/cpp/cpp-tutorials/g_unordered_map-rehash-in-c-stl.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值