我编写了一个示例代码来比较 std::unordered_set 和 std::set 的性能。
constexpr size_t kLoopNumber = 10000000;
std::default_random_engine e;
std::set<uint32_t> s1;
std::unordered_set<uint32_t> s2;
for (size_t i = 0; i < 10000; ++i) {
uint32_t k = e();
s1.emplace(k);
s2.emplace(k);
}
std::vector<size_t> indices(kLoopNumber);
std::iota(indices.begin(), indices.end(), 0);
// std::shuffle(indices.begin(), indices.end(), e);
size_t count = 0;
auto pre = system_clock::now();
// code 0
for (size_t i = 0; i < kLoopNumber; ++i) {
count += s1.count(indices[i]);
}
//
std::cout << duration_cast<microseconds>(system_clock::now() - pre).count()
<< " us for set" << std::endl;
pre = system_clock::now();
// code 1
for (size_t i = 0; i < kLoopNumber; ++i) {
count += s2.count(indices[i]);
}
//
std::cout << duration_cast<microseconds>(system_clock::now() - pre).count()
<< " us for unordered_set" << std::endl;
// for not optimize count
std::cout << count << std::endl;
得到如下结果:
85434 us for set
144212 us for unordered_set
如果我打乱索引。
constexpr size_t kLoopNumber = 10000000;
std::default_random_engine e;
std::set<uint32_t> s1;
std::unordered_set<uint32_t> s2;
for (size_t i = 0; i < 10000; ++i) {
uint32_t k = e();
s1.emplace(k);
s2.emplace(k);
}
std::vector<size_t> indices(kLoopNumber);
std::iota(indices.begin(), indices.end(), 0);
std::shuffle(indices.begin(), indices.end(), e);
size_t count = 0;
auto pre = system_clock::now();
// code 0
for (size_t i = 0; i < kLoopNumber; ++i) {
count += s1.count(indices[i]);
}
//
std::cout << duration_cast<microseconds>(system_clock::now() - pre).count()
<< " us for set" << std::endl;
pre = system_clock::now();
// code 1
for (size_t i = 0; i < kLoopNumber; ++i) {
count += s2.count(indices[i]);
}
//
std::cout << duration_cast<microseconds>(system_clock::now() - pre).count()
<< " us for unordered_set" << std::endl;
// for not optimize count
std::cout << count << std::endl;
然后得到:
225042 us for set
160389 us for unordered_set
为什么洗牌后个人资料变化如此之大,有人可以解释一个重要原因吗? CPU缓存?有序设置键?还是其他原因?
提示:
编译器是 gcc 7.5.0,带有编译选项 g++ -std=c++17 -O2
。
PS:我更新了参考评论建议的示例代码。