Skip to content

Commit 0102da7

Browse files
committed
Add size check to __hash_table::find() and update benchmark cases
1 parent bc3ce69 commit 0102da7

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

libcxx/include/__hash_table

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,7 +1772,7 @@ template <class _Key>
17721772
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
17731773
__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) {
17741774
size_type __bc = bucket_count();
1775-
if (__bc != 0) {
1775+
if (__bc != 0 && size() != 0) {
17761776
size_t __hash = hash_function()(__k);
17771777
size_t __chash = std::__constrain_hash(__hash, __bc);
17781778
__next_pointer __nd = __bucket_list_[__chash];
@@ -1793,7 +1793,7 @@ template <class _Key>
17931793
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
17941794
__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const {
17951795
size_type __bc = bucket_count();
1796-
if (__bc != 0) {
1796+
if (__bc != 0 && size() != 0) {
17971797
size_t __hash = hash_function()(__k);
17981798
size_t __chash = std::__constrain_hash(__hash, __bc);
17991799
__next_pointer __nd = __bucket_list_[__chash];

libcxx/test/benchmarks/containers/associative/hash_table_find.bench.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
1010

1111
#include <unordered_set>
1212
#include <string>
@@ -46,9 +46,9 @@ std::vector<std::string> LongStringGenerator::cached_strings;
4646
}();
4747

4848
template <class Gen>
49-
static void BM_UnorderedSet_Find_EmptySet(benchmark::State& state, Gen g) {
49+
static void BM_UnorderedSet_Find_EmptyNoBuckets(benchmark::State& state, Gen g) {
5050
const size_t lookup_count = state.range(0);
51-
std::unordered_set<std::string> s; // Empty set
51+
std::unordered_set<std::string> s; // Empty and no buckets
5252

5353
for (auto _ : state) {
5454
for (size_t i = 0; i < lookup_count; i++) {
@@ -58,9 +58,10 @@ static void BM_UnorderedSet_Find_EmptySet(benchmark::State& state, Gen g) {
5858
}
5959

6060
template <class Gen>
61-
static void BM_UnorderedSet_Find(benchmark::State& state, Gen g) {
61+
static void BM_UnorderedSet_Find_EmptyWithBuckets(benchmark::State& state, Gen g) {
6262
const size_t lookup_count = state.range(0);
63-
std::unordered_set<std::string> s{"hello"}; // Non-empty set
63+
std::unordered_set<std::string> s;
64+
s.reserve(1); // Still empty but reserved buckets
6465

6566
for (auto _ : state) {
6667
for (size_t i = 0; i < lookup_count; i++) {
@@ -69,12 +70,28 @@ static void BM_UnorderedSet_Find(benchmark::State& state, Gen g) {
6970
}
7071
}
7172

72-
BENCHMARK_CAPTURE(BM_UnorderedSet_Find_EmptySet, long_string, LongStringGenerator())
73+
template <class Gen>
74+
static void BM_UnorderedSet_Find_NonEmpty(benchmark::State& state, Gen g) {
75+
const size_t lookup_count = state.range(0);
76+
std::unordered_set<std::string> s{"hello"};
77+
78+
for (auto _ : state) {
79+
for (size_t i = 0; i < lookup_count; i++) {
80+
benchmark::DoNotOptimize(s.find(g.generate(i)));
81+
}
82+
}
83+
}
84+
85+
BENCHMARK_CAPTURE(BM_UnorderedSet_Find_EmptyNoBuckets, long_string, LongStringGenerator())
7386
->RangeMultiplier(2)
7487
->Range(1 << 10, 1 << 15); // Test from 1K to 32K lookups
7588

76-
BENCHMARK_CAPTURE(BM_UnorderedSet_Find, long_string, LongStringGenerator())
89+
BENCHMARK_CAPTURE(BM_UnorderedSet_Find_EmptyWithBuckets, long_string, LongStringGenerator())
7790
->RangeMultiplier(2)
78-
->Range(1 << 10, 1 << 15); // Test from 1K to 32K lookups
91+
->Range(1 << 10, 1 << 15);
92+
93+
BENCHMARK_CAPTURE(BM_UnorderedSet_Find_NonEmpty, long_string, LongStringGenerator())
94+
->RangeMultiplier(2)
95+
->Range(1 << 10, 1 << 15);
7996

8097
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)