作者:黄可麟66032 | 来源:互联网 | 2023-03-19 05:21
当然,unordered_map的查找性能平均是常量,并且映射的查找性能是O(logN).
但是当然为了在unordered_map中找到一个对象,我们必须:
哈希我们想要找到的密钥.
equality_compare键与同一个桶中的每个键.
而在地图中,我们只需要将所搜索的密钥与log2(N)密钥进行比较,其中N是地图中的项目数.
我想知道真正的性能差异是什么,假设散列函数增加了开销并且equality_compare不比less_than比较便宜.
我写了一个测试,而不是用一个我可以自己回答的问题打扰社区.
我已经分享了下面的结果,以防其他人发现这个有趣或有用.
如果有人能够并且愿意添加更多信息,当然会邀请更多答案.
1> Richard Hodg..:
在回答有关错过搜索次数的性能问题时,我重构了测试以对此进行参数化.
示例结果:
searches=1000000 set_size= 0 miss= 100% ordered= 4384 unordered= 12901 flat_map= 681
searches=1000000 set_size= 99 miss= 99.99% ordered= 89127 unordered= 42615 flat_map= 86091
searches=1000000 set_size= 172 miss= 99.98% ordered= 101283 unordered= 53468 flat_map= 96008
searches=1000000 set_size= 303 miss= 99.97% ordered= 112747 unordered= 53211 flat_map= 107343
searches=1000000 set_size= 396 miss= 99.96% ordered= 124179 unordered= 59655 flat_map= 112687
searches=1000000 set_size= 523 miss= 99.95% ordered= 132180 unordered= 51133 flat_map= 121669
searches=1000000 set_size= 599 miss= 99.94% ordered= 135850 unordered= 55078 flat_map= 121072
searches=1000000 set_size= 695 miss= 99.93% ordered= 140204 unordered= 60087 flat_map= 124961
searches=1000000 set_size= 795 miss= 99.92% ordered= 146071 unordered= 64790 flat_map= 127873
searches=1000000 set_size= 916 miss= 99.91% ordered= 154461 unordered= 50944 flat_map= 133194
searches=1000000 set_size= 988 miss= 99.9% ordered= 156327 unordered= 54094 flat_map= 134288
键:
searches = number of searches performed against each map
set_size = how big each map is (and therefore how many of the searches will result in a hit)
miss = the probability of generating a missed search. Used for generating searches and set_size.
ordered = the time spent searching the ordered map
unordered = the time spent searching the unordered_map
flat_map = the time spent searching the flat map
note: time is measured in std::system_clock::duration ticks.
TL; DR
结果:只要地图中有数据,unordered_map就会显示其优越性.唯一一次表现出比有序地图更差的表现是地图是空的.
这是新代码:
#include
#include
#include
#include
#include
#include
#include
2> Richard Hodg..:
在下面的测试中,我使用-O3在Apple clang上进行了编译,我采取了一些措施来确保测试是公平的,例如:
通过vtable调用每次接收结果的接收器函数,以防止优化程序内联整个搜索!
在3种不同的包含相同数据的地图上,以相同的顺序并行运行测试。这意味着,如果一个测试开始“领先”,它将开始为搜索集输入缓存缺失区域(请参见代码)。这意味着没有人会遇到遇到“热”缓存的不公平优势。
参数化密钥大小(以及复杂度)
参数化地图大小
测试了三种不同类型的地图(包含相同的数据)-unordered_map,地图和键/值对的排序向量。
检查汇编器输出,以确保优化器由于死代码分析而无法优化掉整个逻辑块。
这是代码:
#include
#include
#include
#include
#include
#include