diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index d7b312f8774fc..60f292c86719a 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -1771,9 +1771,9 @@ template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) { - size_t __hash = hash_function()(__k); size_type __bc = bucket_count(); - if (__bc != 0) { + if (__bc != 0 && size() != 0) { + size_t __hash = hash_function()(__k); size_t __chash = std::__constrain_hash(__hash, __bc); __next_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { @@ -1792,9 +1792,9 @@ template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const { - size_t __hash = hash_function()(__k); size_type __bc = bucket_count(); - if (__bc != 0) { + if (__bc != 0 && size() != 0) { + size_t __hash = hash_function()(__k); size_t __chash = std::__constrain_hash(__hash, __bc); __next_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { diff --git a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h index fb4455c4aa9da..2f6115c5698dd 100644 --- a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h +++ b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h @@ -47,6 +47,14 @@ void associative_container_benchmarks(std::string container) { return std::vector(keys.begin(), keys.end()); }; + auto generate_expensive_keys = [=](std::size_t n) { + std::vector keys; + for (std::size_t i = 0; i < n; ++i) { + keys.push_back(Generate::expensive()); + } + return keys; + }; + auto make_value_types = [](std::vector const& keys) { std::vector kv; for (Key const& k : keys) @@ -480,17 +488,37 @@ void associative_container_benchmarks(std::string container) { }; }; + auto with_expensive_key_empty = [=](auto func) { + return [=](auto& st) { + const std::size_t size = st.range(0); + std::vector keys = generate_expensive_keys(size); + Container c; + + while (st.KeepRunningBatch(BatchSize)) { + for (std::size_t i = 0; i != BatchSize; ++i) { + auto result = func(c, keys[i]); + benchmark::DoNotOptimize(c); + benchmark::DoNotOptimize(result); + benchmark::ClobberMemory(); + } + } + }; + }; + auto find = [](Container const& c, Key const& key) { return c.find(key); }; bench("find(key) (existent)", with_existent_key(find)); bench("find(key) (non-existent)", with_nonexistent_key(find)); + bench("find(key) (expensive-empty)", with_expensive_key_empty(find)); auto count = [](Container const& c, Key const& key) { return c.count(key); }; bench("count(key) (existent)", with_existent_key(count)); bench("count(key) (non-existent)", with_nonexistent_key(count)); + bench("count(key) (expensive-empty)", with_expensive_key_empty(count)); auto contains = [](Container const& c, Key const& key) { return c.contains(key); }; bench("contains(key) (existent)", with_existent_key(contains)); bench("contains(key) (non-existent)", with_nonexistent_key(contains)); + bench("contains(key) (expensive-empty)", with_expensive_key_empty(contains)); if constexpr (is_ordered_container) { auto lower_bound = [](Container const& c, Key const& key) { return c.lower_bound(key); }; diff --git a/libcxx/test/benchmarks/containers/associative/unordered_map.bench.cpp b/libcxx/test/benchmarks/containers/associative/unordered_map.bench.cpp index 57adec2d214d4..89fddccb4d531 100644 --- a/libcxx/test/benchmarks/containers/associative/unordered_map.bench.cpp +++ b/libcxx/test/benchmarks/containers/associative/unordered_map.bench.cpp @@ -28,6 +28,7 @@ struct support::adapt_operations> { int main(int argc, char** argv) { support::associative_container_benchmarks>("std::unordered_map"); + support::associative_container_benchmarks>("std::unordered_map"); benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); diff --git a/libcxx/test/benchmarks/containers/associative/unordered_multimap.bench.cpp b/libcxx/test/benchmarks/containers/associative/unordered_multimap.bench.cpp index 8738ca4bf9f0c..080cf61087ddd 100644 --- a/libcxx/test/benchmarks/containers/associative/unordered_multimap.bench.cpp +++ b/libcxx/test/benchmarks/containers/associative/unordered_multimap.bench.cpp @@ -27,6 +27,7 @@ struct support::adapt_operations> { int main(int argc, char** argv) { support::associative_container_benchmarks>("std::unordered_multimap"); + support::associative_container_benchmarks>("std::unordered_multimap"); benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); diff --git a/libcxx/test/benchmarks/containers/associative/unordered_multiset.bench.cpp b/libcxx/test/benchmarks/containers/associative/unordered_multiset.bench.cpp index 4888b01bfeba0..c4e1dc4c42651 100644 --- a/libcxx/test/benchmarks/containers/associative/unordered_multiset.bench.cpp +++ b/libcxx/test/benchmarks/containers/associative/unordered_multiset.bench.cpp @@ -8,6 +8,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 +#include #include #include "associative_container_benchmarks.h" @@ -26,6 +27,7 @@ struct support::adapt_operations> { int main(int argc, char** argv) { support::associative_container_benchmarks>("std::unordered_multiset"); + support::associative_container_benchmarks>("std::unordered_multiset"); benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); diff --git a/libcxx/test/benchmarks/containers/associative/unordered_set.bench.cpp b/libcxx/test/benchmarks/containers/associative/unordered_set.bench.cpp index 56420bdaadfbf..89443a597e85a 100644 --- a/libcxx/test/benchmarks/containers/associative/unordered_set.bench.cpp +++ b/libcxx/test/benchmarks/containers/associative/unordered_set.bench.cpp @@ -8,6 +8,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 +#include #include #include @@ -27,6 +28,7 @@ struct support::adapt_operations> { int main(int argc, char** argv) { support::associative_container_benchmarks>("std::unordered_set"); + support::associative_container_benchmarks>("std::unordered_set"); benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks();