1 #include <unordered_set>
8 #include "benchmark/benchmark.h"
10 #include "ContainerBenchmarks.h"
11 #include "GenerateInput.h"
12 #include "test_macros.h"
14 using namespace ContainerBenchmarks
;
16 constexpr std::size_t TestNumInputs
= 1024;
18 template <class _Size
>
19 inline TEST_ALWAYS_INLINE
20 _Size
loadword(const void* __p
) {
22 std::memcpy(&__r
, __p
, sizeof(__r
));
26 inline TEST_ALWAYS_INLINE
27 std::size_t rotate_by_at_least_1(std::size_t __val
, int __shift
) {
28 return (__val
>> __shift
) | (__val
<< (64 - __shift
));
31 inline TEST_ALWAYS_INLINE
32 std::size_t hash_len_16(std::size_t __u
, std::size_t __v
) {
33 const std::size_t __mul
= 0x9ddfea08eb382d69ULL
;
34 std::size_t __a
= (__u
^ __v
) * __mul
;
36 std::size_t __b
= (__v
^ __a
) * __mul
;
43 template <std::size_t _Len
>
44 inline TEST_ALWAYS_INLINE
45 std::size_t hash_len_0_to_8(const char* __s
) {
46 static_assert(_Len
== 4 || _Len
== 8, "");
47 const uint64_t __a
= loadword
<uint32_t>(__s
);
48 const uint64_t __b
= loadword
<uint32_t>(__s
+ _Len
- 4);
49 return hash_len_16(_Len
+ (__a
<< 3), __b
);
53 UInt32Hash() = default;
54 inline TEST_ALWAYS_INLINE
55 std::size_t operator()(uint32_t data
) const {
56 return hash_len_0_to_8
<4>(reinterpret_cast<const char*>(&data
));
61 UInt64Hash() = default;
62 inline TEST_ALWAYS_INLINE
63 std::size_t operator()(uint64_t data
) const {
64 return hash_len_0_to_8
<8>(reinterpret_cast<const char*>(&data
));
69 UInt128Hash() = default;
70 inline TEST_ALWAYS_INLINE
71 std::size_t operator()(__uint128_t data
) const {
72 const __uint128_t __mask
= static_cast<std::size_t>(-1);
73 const std::size_t __a
= (std::size_t)(data
& __mask
);
74 const std::size_t __b
= (std::size_t)((data
& (__mask
<< 64)) >> 64);
75 return hash_len_16(__a
, rotate_by_at_least_1(__b
+ 16, 16)) ^ __b
;
80 UInt32Hash2() = default;
81 inline TEST_ALWAYS_INLINE
82 std::size_t operator()(uint32_t data
) const {
83 const uint32_t __m
= 0x5bd1e995;
84 const uint32_t __r
= 24;
100 UInt64Hash2() = default;
101 inline TEST_ALWAYS_INLINE
102 std::size_t operator()(uint64_t data
) const {
103 return hash_len_0_to_8
<8>(reinterpret_cast<const char*>(&data
));
107 //----------------------------------------------------------------------------//
109 // ---------------------------------------------------------------------------//
111 template <class HashFn
, class GenInputs
>
112 void BM_Hash(benchmark::State
& st
, HashFn fn
, GenInputs gen
) {
113 auto in
= gen(st
.range(0));
114 const auto end
= in
.data() + in
.size();
115 std::size_t last_hash
= 0;
116 benchmark::DoNotOptimize(&last_hash
);
117 while (st
.KeepRunning()) {
118 for (auto it
= in
.data(); it
!= end
; ++it
) {
119 benchmark::DoNotOptimize(last_hash
+= fn(*it
));
121 benchmark::ClobberMemory();
125 BENCHMARK_CAPTURE(BM_Hash
,
126 uint32_random_std_hash
,
127 std::hash
<uint32_t>{},
128 getRandomIntegerInputs
<uint32_t>) -> Arg(TestNumInputs
);
130 BENCHMARK_CAPTURE(BM_Hash
,
131 uint32_random_custom_hash
,
133 getRandomIntegerInputs
<uint32_t>) -> Arg(TestNumInputs
);
135 BENCHMARK_CAPTURE(BM_Hash
,
137 std::hash
<uint32_t>{},
138 getSortedTopBitsIntegerInputs
<uint32_t>) -> Arg(TestNumInputs
);
140 BENCHMARK_CAPTURE(BM_Hash
,
141 uint32_top_custom_hash
,
143 getSortedTopBitsIntegerInputs
<uint32_t>) -> Arg(TestNumInputs
);
146 //----------------------------------------------------------------------------//
148 // ---------------------------------------------------------------------------//
151 // Sorted Ascending //
152 BENCHMARK_CAPTURE(BM_InsertValue
,
153 unordered_set_uint32
,
154 std::unordered_set
<uint32_t>{},
155 getRandomIntegerInputs
<uint32_t>)->Arg(TestNumInputs
);
157 BENCHMARK_CAPTURE(BM_InsertValue
,
158 unordered_set_uint32_sorted
,
159 std::unordered_set
<uint32_t>{},
160 getSortedIntegerInputs
<uint32_t>)->Arg(TestNumInputs
);
163 BENCHMARK_CAPTURE(BM_InsertValue
,
164 unordered_set_top_bits_uint32
,
165 std::unordered_set
<uint32_t>{},
166 getSortedTopBitsIntegerInputs
<uint32_t>)->Arg(TestNumInputs
);
168 BENCHMARK_CAPTURE(BM_InsertValueRehash
,
169 unordered_set_top_bits_uint32
,
170 std::unordered_set
<uint32_t, UInt32Hash
>{},
171 getSortedTopBitsIntegerInputs
<uint32_t>)->Arg(TestNumInputs
);
174 BENCHMARK_CAPTURE(BM_InsertValue
,
175 unordered_set_string
,
176 std::unordered_set
<std::string
>{},
177 getRandomStringInputs
)->Arg(TestNumInputs
);
179 BENCHMARK_CAPTURE(BM_InsertValueRehash
,
180 unordered_set_string
,
181 std::unordered_set
<std::string
>{},
182 getRandomStringInputs
)->Arg(TestNumInputs
);
184 //----------------------------------------------------------------------------//
186 // ---------------------------------------------------------------------------//
189 BENCHMARK_CAPTURE(BM_Find
,
190 unordered_set_random_uint64
,
191 std::unordered_set
<uint64_t>{},
192 getRandomIntegerInputs
<uint64_t>)->Arg(TestNumInputs
);
194 BENCHMARK_CAPTURE(BM_FindRehash
,
195 unordered_set_random_uint64
,
196 std::unordered_set
<uint64_t, UInt64Hash
>{},
197 getRandomIntegerInputs
<uint64_t>)->Arg(TestNumInputs
);
200 BENCHMARK_CAPTURE(BM_Find
,
201 unordered_set_sorted_uint64
,
202 std::unordered_set
<uint64_t>{},
203 getSortedIntegerInputs
<uint64_t>)->Arg(TestNumInputs
);
205 BENCHMARK_CAPTURE(BM_FindRehash
,
206 unordered_set_sorted_uint64
,
207 std::unordered_set
<uint64_t, UInt64Hash
>{},
208 getSortedIntegerInputs
<uint64_t>)->Arg(TestNumInputs
);
213 BENCHMARK_CAPTURE(BM_Find
,
214 unordered_set_sorted_uint128
,
215 std::unordered_set
<__uint128_t
, UInt128Hash
>{},
216 getSortedTopBitsIntegerInputs
<__uint128_t
>)->Arg(TestNumInputs
);
218 BENCHMARK_CAPTURE(BM_FindRehash
,
219 unordered_set_sorted_uint128
,
220 std::unordered_set
<__uint128_t
, UInt128Hash
>{},
221 getSortedTopBitsIntegerInputs
<__uint128_t
>)->Arg(TestNumInputs
);
225 BENCHMARK_CAPTURE(BM_Find
,
226 unordered_set_sorted_uint32
,
227 std::unordered_set
<uint32_t>{},
228 getSortedIntegerInputs
<uint32_t>)->Arg(TestNumInputs
);
230 BENCHMARK_CAPTURE(BM_FindRehash
,
231 unordered_set_sorted_uint32
,
232 std::unordered_set
<uint32_t, UInt32Hash2
>{},
233 getSortedIntegerInputs
<uint32_t>)->Arg(TestNumInputs
);
235 // Sorted Ascending //
236 BENCHMARK_CAPTURE(BM_Find
,
237 unordered_set_sorted_large_uint64
,
238 std::unordered_set
<uint64_t>{},
239 getSortedLargeIntegerInputs
<uint64_t>)->Arg(TestNumInputs
);
241 BENCHMARK_CAPTURE(BM_FindRehash
,
242 unordered_set_sorted_large_uint64
,
243 std::unordered_set
<uint64_t, UInt64Hash
>{},
244 getSortedLargeIntegerInputs
<uint64_t>)->Arg(TestNumInputs
);
248 BENCHMARK_CAPTURE(BM_Find
,
249 unordered_set_top_bits_uint64
,
250 std::unordered_set
<uint64_t>{},
251 getSortedTopBitsIntegerInputs
<uint64_t>)->Arg(TestNumInputs
);
253 BENCHMARK_CAPTURE(BM_FindRehash
,
254 unordered_set_top_bits_uint64
,
255 std::unordered_set
<uint64_t, UInt64Hash
>{},
256 getSortedTopBitsIntegerInputs
<uint64_t>)->Arg(TestNumInputs
);
259 BENCHMARK_CAPTURE(BM_Find
,
260 unordered_set_string
,
261 std::unordered_set
<std::string
>{},
262 getRandomStringInputs
)->Arg(TestNumInputs
);
264 BENCHMARK_CAPTURE(BM_FindRehash
,
265 unordered_set_string
,
266 std::unordered_set
<std::string
>{},
267 getRandomStringInputs
)->Arg(TestNumInputs
);
269 ///////////////////////////////////////////////////////////////////////////////
270 BENCHMARK_CAPTURE(BM_InsertDuplicate
,
272 std::unordered_set
<int>{},
273 getRandomIntegerInputs
<int>)->Arg(TestNumInputs
);
274 BENCHMARK_CAPTURE(BM_InsertDuplicate
,
275 unordered_set_string
,
276 std::unordered_set
<std::string
>{},
277 getRandomStringInputs
)->Arg(TestNumInputs
);
279 BENCHMARK_CAPTURE(BM_EmplaceDuplicate
,
281 std::unordered_set
<int>{},
282 getRandomIntegerInputs
<int>)->Arg(TestNumInputs
);
283 BENCHMARK_CAPTURE(BM_EmplaceDuplicate
,
284 unordered_set_string
,
285 std::unordered_set
<std::string
>{},
286 getRandomStringInputs
)->Arg(TestNumInputs
);
288 BENCHMARK_CAPTURE(BM_InsertDuplicate
,
289 unordered_set_int_insert_arg
,
290 std::unordered_set
<int>{},
291 getRandomIntegerInputs
<int>)->Arg(TestNumInputs
);
292 BENCHMARK_CAPTURE(BM_InsertDuplicate
,
293 unordered_set_string_insert_arg
,
294 std::unordered_set
<std::string
>{},
295 getRandomStringInputs
)->Arg(TestNumInputs
);
297 BENCHMARK_CAPTURE(BM_EmplaceDuplicate
,
298 unordered_set_int_insert_arg
,
299 std::unordered_set
<int>{},
300 getRandomIntegerInputs
<unsigned>)->Arg(TestNumInputs
);
302 BENCHMARK_CAPTURE(BM_EmplaceDuplicate
,
303 unordered_set_string_arg
,
304 std::unordered_set
<std::string
>{},
305 getRandomCStringInputs
)->Arg(TestNumInputs
);