xref: /openbsd-src/gnu/llvm/libcxx/benchmarks/map.bench.cpp (revision 76d0caaeb19ae0808d90af1d0b3b7b50b3e5383f)
1*76d0caaeSpatrick //===----------------------------------------------------------------------===//
2*76d0caaeSpatrick //
3*76d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*76d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information.
5*76d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*76d0caaeSpatrick //
7*76d0caaeSpatrick //===----------------------------------------------------------------------===//
8*76d0caaeSpatrick 
9*76d0caaeSpatrick #include <algorithm>
10*76d0caaeSpatrick #include <cstdint>
11*76d0caaeSpatrick #include <map>
12*76d0caaeSpatrick #include <random>
13*76d0caaeSpatrick #include <vector>
14*76d0caaeSpatrick 
15*76d0caaeSpatrick #include "CartesianBenchmarks.h"
16*76d0caaeSpatrick #include "benchmark/benchmark.h"
17*76d0caaeSpatrick #include "test_macros.h"
18*76d0caaeSpatrick 
19*76d0caaeSpatrick // When VALIDATE is defined the benchmark will run to validate the benchmarks.
20*76d0caaeSpatrick // The time taken by several operations depend on whether or not an element
21*76d0caaeSpatrick // exists. To avoid errors in the benchmark these operations have a validation
22*76d0caaeSpatrick // mode to test the benchmark. Since they are not meant to be benchmarked the
23*76d0caaeSpatrick // number of sizes tested is limited to 1.
24*76d0caaeSpatrick //#define VALIDATE
25*76d0caaeSpatrick 
26*76d0caaeSpatrick namespace {
27*76d0caaeSpatrick 
28*76d0caaeSpatrick enum class Mode { Hit, Miss };
29*76d0caaeSpatrick 
30*76d0caaeSpatrick struct AllModes : EnumValuesAsTuple<AllModes, Mode, 2> {
31*76d0caaeSpatrick   static constexpr const char* Names[] = {"ExistingElement", "NewElement"};
32*76d0caaeSpatrick };
33*76d0caaeSpatrick 
34*76d0caaeSpatrick // The positions of the hints to pick:
35*76d0caaeSpatrick // - Begin picks the first item. The item cannot be put before this element.
36*76d0caaeSpatrick // - Thrid picks the third item. This is just an element with a valid entry
37*76d0caaeSpatrick //   before and after it.
38*76d0caaeSpatrick // - Correct contains the correct hint.
39*76d0caaeSpatrick // - End contains a hint to the end of the map.
40*76d0caaeSpatrick enum class Hint { Begin, Third, Correct, End };
41*76d0caaeSpatrick struct AllHints : EnumValuesAsTuple<AllHints, Hint, 4> {
42*76d0caaeSpatrick   static constexpr const char* Names[] = {"Begin", "Third", "Correct", "End"};
43*76d0caaeSpatrick };
44*76d0caaeSpatrick 
45*76d0caaeSpatrick enum class Order { Sorted, Random };
46*76d0caaeSpatrick struct AllOrders : EnumValuesAsTuple<AllOrders, Order, 2> {
47*76d0caaeSpatrick   static constexpr const char* Names[] = {"Sorted", "Random"};
48*76d0caaeSpatrick };
49*76d0caaeSpatrick 
50*76d0caaeSpatrick struct TestSets {
51*76d0caaeSpatrick   std::vector<uint64_t> Keys;
52*76d0caaeSpatrick   std::vector<std::map<uint64_t, int64_t> > Maps;
53*76d0caaeSpatrick   std::vector<
54*76d0caaeSpatrick       std::vector<typename std::map<uint64_t, int64_t>::const_iterator> >
55*76d0caaeSpatrick       Hints;
56*76d0caaeSpatrick };
57*76d0caaeSpatrick 
58*76d0caaeSpatrick enum class Shuffle { None, Keys, Hints };
59*76d0caaeSpatrick 
makeTestingSets(size_t MapSize,Mode mode,Shuffle shuffle,size_t max_maps)60*76d0caaeSpatrick TestSets makeTestingSets(size_t MapSize, Mode mode, Shuffle shuffle,
61*76d0caaeSpatrick                          size_t max_maps) {
62*76d0caaeSpatrick   /*
63*76d0caaeSpatrick    * The shuffle does not retain the random number generator to use the same
64*76d0caaeSpatrick    * set of random numbers for every iteration.
65*76d0caaeSpatrick    */
66*76d0caaeSpatrick   TestSets R;
67*76d0caaeSpatrick 
68*76d0caaeSpatrick   int MapCount = std::min(max_maps, 1000000 / MapSize);
69*76d0caaeSpatrick 
70*76d0caaeSpatrick   for (uint64_t I = 0; I < MapSize; ++I) {
71*76d0caaeSpatrick     R.Keys.push_back(mode == Mode::Hit ? 2 * I + 2 : 2 * I + 1);
72*76d0caaeSpatrick   }
73*76d0caaeSpatrick   if (shuffle == Shuffle::Keys)
74*76d0caaeSpatrick     std::shuffle(R.Keys.begin(), R.Keys.end(), std::mt19937());
75*76d0caaeSpatrick 
76*76d0caaeSpatrick   for (int M = 0; M < MapCount; ++M) {
77*76d0caaeSpatrick     auto& map = R.Maps.emplace_back();
78*76d0caaeSpatrick     auto& hints = R.Hints.emplace_back();
79*76d0caaeSpatrick     for (uint64_t I = 0; I < MapSize; ++I) {
80*76d0caaeSpatrick       hints.push_back(map.insert(std::make_pair(2 * I + 2, 0)).first);
81*76d0caaeSpatrick     }
82*76d0caaeSpatrick     if (shuffle == Shuffle::Hints)
83*76d0caaeSpatrick       std::shuffle(hints.begin(), hints.end(), std::mt19937());
84*76d0caaeSpatrick   }
85*76d0caaeSpatrick 
86*76d0caaeSpatrick   return R;
87*76d0caaeSpatrick }
88*76d0caaeSpatrick 
89*76d0caaeSpatrick struct Base {
90*76d0caaeSpatrick   size_t MapSize;
Base__anona63cc8890111::Base91*76d0caaeSpatrick   Base(size_t T) : MapSize(T) {}
92*76d0caaeSpatrick 
baseName__anona63cc8890111::Base93*76d0caaeSpatrick   std::string baseName() const { return "_MapSize=" + std::to_string(MapSize); }
94*76d0caaeSpatrick };
95*76d0caaeSpatrick 
96*76d0caaeSpatrick //*******************************************************************|
97*76d0caaeSpatrick //                       Member functions                            |
98*76d0caaeSpatrick //*******************************************************************|
99*76d0caaeSpatrick 
100*76d0caaeSpatrick struct ConstructorDefault {
run__anona63cc8890111::ConstructorDefault101*76d0caaeSpatrick   void run(benchmark::State& State) const {
102*76d0caaeSpatrick     for (auto _ : State) {
103*76d0caaeSpatrick       benchmark::DoNotOptimize(std::map<uint64_t, int64_t>());
104*76d0caaeSpatrick     }
105*76d0caaeSpatrick   }
106*76d0caaeSpatrick 
name__anona63cc8890111::ConstructorDefault107*76d0caaeSpatrick   std::string name() const { return "BM_ConstructorDefault"; }
108*76d0caaeSpatrick };
109*76d0caaeSpatrick 
110*76d0caaeSpatrick struct ConstructorIterator : Base {
111*76d0caaeSpatrick   using Base::Base;
112*76d0caaeSpatrick 
run__anona63cc8890111::ConstructorIterator113*76d0caaeSpatrick   void run(benchmark::State& State) const {
114*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1);
115*76d0caaeSpatrick     auto& Map = Data.Maps.front();
116*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize)) {
117*76d0caaeSpatrick #ifndef VALIDATE
118*76d0caaeSpatrick       benchmark::DoNotOptimize(
119*76d0caaeSpatrick           std::map<uint64_t, int64_t>(Map.begin(), Map.end()));
120*76d0caaeSpatrick #else
121*76d0caaeSpatrick       std::map<uint64_t, int64_t> M{Map.begin(), Map.end()};
122*76d0caaeSpatrick       if (M != Map)
123*76d0caaeSpatrick         State.SkipWithError("Map copy not identical");
124*76d0caaeSpatrick #endif
125*76d0caaeSpatrick     }
126*76d0caaeSpatrick   }
127*76d0caaeSpatrick 
name__anona63cc8890111::ConstructorIterator128*76d0caaeSpatrick   std::string name() const { return "BM_ConstructorIterator" + baseName(); }
129*76d0caaeSpatrick };
130*76d0caaeSpatrick 
131*76d0caaeSpatrick struct ConstructorCopy : Base {
132*76d0caaeSpatrick   using Base::Base;
133*76d0caaeSpatrick 
run__anona63cc8890111::ConstructorCopy134*76d0caaeSpatrick   void run(benchmark::State& State) const {
135*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1);
136*76d0caaeSpatrick     auto& Map = Data.Maps.front();
137*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize)) {
138*76d0caaeSpatrick #ifndef VALIDATE
139*76d0caaeSpatrick       std::map<uint64_t, int64_t> M(Map);
140*76d0caaeSpatrick       benchmark::DoNotOptimize(M);
141*76d0caaeSpatrick #else
142*76d0caaeSpatrick       std::map<uint64_t, int64_t> M(Map);
143*76d0caaeSpatrick       if (M != Map)
144*76d0caaeSpatrick         State.SkipWithError("Map copy not identical");
145*76d0caaeSpatrick #endif
146*76d0caaeSpatrick     }
147*76d0caaeSpatrick   }
148*76d0caaeSpatrick 
name__anona63cc8890111::ConstructorCopy149*76d0caaeSpatrick   std::string name() const { return "BM_ConstructorCopy" + baseName(); }
150*76d0caaeSpatrick };
151*76d0caaeSpatrick 
152*76d0caaeSpatrick struct ConstructorMove : Base {
153*76d0caaeSpatrick   using Base::Base;
154*76d0caaeSpatrick 
run__anona63cc8890111::ConstructorMove155*76d0caaeSpatrick   void run(benchmark::State& State) const {
156*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000);
157*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
158*76d0caaeSpatrick       for (auto& Map : Data.Maps) {
159*76d0caaeSpatrick         std::map<uint64_t, int64_t> M(std::move(Map));
160*76d0caaeSpatrick         benchmark::DoNotOptimize(M);
161*76d0caaeSpatrick       }
162*76d0caaeSpatrick       State.PauseTiming();
163*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000);
164*76d0caaeSpatrick       State.ResumeTiming();
165*76d0caaeSpatrick     }
166*76d0caaeSpatrick   }
167*76d0caaeSpatrick 
name__anona63cc8890111::ConstructorMove168*76d0caaeSpatrick   std::string name() const { return "BM_ConstructorMove" + baseName(); }
169*76d0caaeSpatrick };
170*76d0caaeSpatrick 
171*76d0caaeSpatrick //*******************************************************************|
172*76d0caaeSpatrick //                           Capacity                                |
173*76d0caaeSpatrick //*******************************************************************|
174*76d0caaeSpatrick 
175*76d0caaeSpatrick struct Empty : Base {
176*76d0caaeSpatrick   using Base::Base;
177*76d0caaeSpatrick 
run__anona63cc8890111::Empty178*76d0caaeSpatrick   void run(benchmark::State& State) const {
179*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1);
180*76d0caaeSpatrick     auto& Map = Data.Maps.front();
181*76d0caaeSpatrick     for (auto _ : State) {
182*76d0caaeSpatrick #ifndef VALIDATE
183*76d0caaeSpatrick       benchmark::DoNotOptimize(Map.empty());
184*76d0caaeSpatrick #else
185*76d0caaeSpatrick       if (Map.empty())
186*76d0caaeSpatrick         State.SkipWithError("Map contains an invalid number of elements.");
187*76d0caaeSpatrick #endif
188*76d0caaeSpatrick     }
189*76d0caaeSpatrick   }
190*76d0caaeSpatrick 
name__anona63cc8890111::Empty191*76d0caaeSpatrick   std::string name() const { return "BM_Empty" + baseName(); }
192*76d0caaeSpatrick };
193*76d0caaeSpatrick 
194*76d0caaeSpatrick struct Size : Base {
195*76d0caaeSpatrick   using Base::Base;
196*76d0caaeSpatrick 
run__anona63cc8890111::Size197*76d0caaeSpatrick   void run(benchmark::State& State) const {
198*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1);
199*76d0caaeSpatrick     auto& Map = Data.Maps.front();
200*76d0caaeSpatrick     for (auto _ : State) {
201*76d0caaeSpatrick #ifndef VALIDATE
202*76d0caaeSpatrick       benchmark::DoNotOptimize(Map.size());
203*76d0caaeSpatrick #else
204*76d0caaeSpatrick       if (Map.size() != MapSize)
205*76d0caaeSpatrick         State.SkipWithError("Map contains an invalid number of elements.");
206*76d0caaeSpatrick #endif
207*76d0caaeSpatrick     }
208*76d0caaeSpatrick   }
209*76d0caaeSpatrick 
name__anona63cc8890111::Size210*76d0caaeSpatrick   std::string name() const { return "BM_Size" + baseName(); }
211*76d0caaeSpatrick };
212*76d0caaeSpatrick 
213*76d0caaeSpatrick //*******************************************************************|
214*76d0caaeSpatrick //                           Modifiers                               |
215*76d0caaeSpatrick //*******************************************************************|
216*76d0caaeSpatrick 
217*76d0caaeSpatrick struct Clear : Base {
218*76d0caaeSpatrick   using Base::Base;
219*76d0caaeSpatrick 
run__anona63cc8890111::Clear220*76d0caaeSpatrick   void run(benchmark::State& State) const {
221*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000);
222*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
223*76d0caaeSpatrick       for (auto& Map : Data.Maps) {
224*76d0caaeSpatrick         Map.clear();
225*76d0caaeSpatrick         benchmark::DoNotOptimize(Map);
226*76d0caaeSpatrick       }
227*76d0caaeSpatrick       State.PauseTiming();
228*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000);
229*76d0caaeSpatrick       State.ResumeTiming();
230*76d0caaeSpatrick     }
231*76d0caaeSpatrick   }
232*76d0caaeSpatrick 
name__anona63cc8890111::Clear233*76d0caaeSpatrick   std::string name() const { return "BM_Clear" + baseName(); }
234*76d0caaeSpatrick };
235*76d0caaeSpatrick 
236*76d0caaeSpatrick template <class Mode, class Order>
237*76d0caaeSpatrick struct Insert : Base {
238*76d0caaeSpatrick   using Base::Base;
239*76d0caaeSpatrick 
run__anona63cc8890111::Insert240*76d0caaeSpatrick   void run(benchmark::State& State) const {
241*76d0caaeSpatrick     auto Data = makeTestingSets(
242*76d0caaeSpatrick         MapSize, Mode(),
243*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1000);
244*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
245*76d0caaeSpatrick       for (auto& Map : Data.Maps) {
246*76d0caaeSpatrick         for (auto K : Data.Keys) {
247*76d0caaeSpatrick #ifndef VALIDATE
248*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.insert(std::make_pair(K, 1)));
249*76d0caaeSpatrick #else
250*76d0caaeSpatrick           bool Inserted = Map.insert(std::make_pair(K, 1)).second;
251*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
252*76d0caaeSpatrick             if (Inserted)
253*76d0caaeSpatrick               State.SkipWithError("Inserted a duplicate element");
254*76d0caaeSpatrick           } else {
255*76d0caaeSpatrick             if (!Inserted)
256*76d0caaeSpatrick               State.SkipWithError("Failed to insert e new element");
257*76d0caaeSpatrick           }
258*76d0caaeSpatrick #endif
259*76d0caaeSpatrick         }
260*76d0caaeSpatrick       }
261*76d0caaeSpatrick 
262*76d0caaeSpatrick       State.PauseTiming();
263*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(),
264*76d0caaeSpatrick                              Order::value == ::Order::Random ? Shuffle::Keys
265*76d0caaeSpatrick                                                              : Shuffle::None,
266*76d0caaeSpatrick                              1000);
267*76d0caaeSpatrick       State.ResumeTiming();
268*76d0caaeSpatrick     }
269*76d0caaeSpatrick   }
270*76d0caaeSpatrick 
name__anona63cc8890111::Insert271*76d0caaeSpatrick   std::string name() const {
272*76d0caaeSpatrick     return "BM_Insert" + baseName() + Mode::name() + Order::name();
273*76d0caaeSpatrick   }
274*76d0caaeSpatrick };
275*76d0caaeSpatrick 
276*76d0caaeSpatrick template <class Mode, class Hint>
277*76d0caaeSpatrick struct InsertHint : Base {
278*76d0caaeSpatrick   using Base::Base;
279*76d0caaeSpatrick 
280*76d0caaeSpatrick   template < ::Hint hint>
281*76d0caaeSpatrick   typename std::enable_if<hint == ::Hint::Correct>::type
run__anona63cc8890111::InsertHint282*76d0caaeSpatrick   run(benchmark::State& State) const {
283*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
284*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
285*76d0caaeSpatrick       for (size_t I = 0; I < Data.Maps.size(); ++I) {
286*76d0caaeSpatrick         auto& Map = Data.Maps[I];
287*76d0caaeSpatrick         auto H = Data.Hints[I].begin();
288*76d0caaeSpatrick         for (auto K : Data.Keys) {
289*76d0caaeSpatrick #ifndef VALIDATE
290*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.insert(*H, std::make_pair(K, 1)));
291*76d0caaeSpatrick #else
292*76d0caaeSpatrick           auto Inserted = Map.insert(*H, std::make_pair(K, 1));
293*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
294*76d0caaeSpatrick             if (Inserted != *H)
295*76d0caaeSpatrick               State.SkipWithError("Inserted a duplicate element");
296*76d0caaeSpatrick           } else {
297*76d0caaeSpatrick             if (++Inserted != *H)
298*76d0caaeSpatrick               State.SkipWithError("Failed to insert a new element");
299*76d0caaeSpatrick           }
300*76d0caaeSpatrick #endif
301*76d0caaeSpatrick           ++H;
302*76d0caaeSpatrick         }
303*76d0caaeSpatrick       }
304*76d0caaeSpatrick 
305*76d0caaeSpatrick       State.PauseTiming();
306*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
307*76d0caaeSpatrick       State.ResumeTiming();
308*76d0caaeSpatrick     }
309*76d0caaeSpatrick   }
310*76d0caaeSpatrick 
311*76d0caaeSpatrick   template < ::Hint hint>
312*76d0caaeSpatrick   typename std::enable_if<hint != ::Hint::Correct>::type
run__anona63cc8890111::InsertHint313*76d0caaeSpatrick   run(benchmark::State& State) const {
314*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
315*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
316*76d0caaeSpatrick       for (size_t I = 0; I < Data.Maps.size(); ++I) {
317*76d0caaeSpatrick         auto& Map = Data.Maps[I];
318*76d0caaeSpatrick         auto Third = *(Data.Hints[I].begin() + 2);
319*76d0caaeSpatrick         for (auto K : Data.Keys) {
320*76d0caaeSpatrick           auto Itor = hint == ::Hint::Begin
321*76d0caaeSpatrick                           ? Map.begin()
322*76d0caaeSpatrick                           : hint == ::Hint::Third ? Third : Map.end();
323*76d0caaeSpatrick #ifndef VALIDATE
324*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.insert(Itor, std::make_pair(K, 1)));
325*76d0caaeSpatrick #else
326*76d0caaeSpatrick           size_t Size = Map.size();
327*76d0caaeSpatrick           Map.insert(Itor, std::make_pair(K, 1));
328*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
329*76d0caaeSpatrick             if (Size != Map.size())
330*76d0caaeSpatrick               State.SkipWithError("Inserted a duplicate element");
331*76d0caaeSpatrick           } else {
332*76d0caaeSpatrick             if (Size + 1 != Map.size())
333*76d0caaeSpatrick               State.SkipWithError("Failed to insert a new element");
334*76d0caaeSpatrick           }
335*76d0caaeSpatrick #endif
336*76d0caaeSpatrick         }
337*76d0caaeSpatrick       }
338*76d0caaeSpatrick 
339*76d0caaeSpatrick       State.PauseTiming();
340*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
341*76d0caaeSpatrick       State.ResumeTiming();
342*76d0caaeSpatrick     }
343*76d0caaeSpatrick   }
344*76d0caaeSpatrick 
run__anona63cc8890111::InsertHint345*76d0caaeSpatrick   void run(benchmark::State& State) const {
346*76d0caaeSpatrick     static constexpr auto h = Hint();
347*76d0caaeSpatrick     run<h>(State);
348*76d0caaeSpatrick   }
349*76d0caaeSpatrick 
name__anona63cc8890111::InsertHint350*76d0caaeSpatrick   std::string name() const {
351*76d0caaeSpatrick     return "BM_InsertHint" + baseName() + Mode::name() + Hint::name();
352*76d0caaeSpatrick   }
353*76d0caaeSpatrick };
354*76d0caaeSpatrick 
355*76d0caaeSpatrick template <class Mode, class Order>
356*76d0caaeSpatrick struct InsertAssign : Base {
357*76d0caaeSpatrick   using Base::Base;
358*76d0caaeSpatrick 
run__anona63cc8890111::InsertAssign359*76d0caaeSpatrick   void run(benchmark::State& State) const {
360*76d0caaeSpatrick     auto Data = makeTestingSets(
361*76d0caaeSpatrick         MapSize, Mode(),
362*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1000);
363*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
364*76d0caaeSpatrick       for (auto& Map : Data.Maps) {
365*76d0caaeSpatrick         for (auto K : Data.Keys) {
366*76d0caaeSpatrick #ifndef VALIDATE
367*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.insert_or_assign(K, 1));
368*76d0caaeSpatrick #else
369*76d0caaeSpatrick           bool Inserted = Map.insert_or_assign(K, 1).second;
370*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
371*76d0caaeSpatrick             if (Inserted)
372*76d0caaeSpatrick               State.SkipWithError("Inserted a duplicate element");
373*76d0caaeSpatrick           } else {
374*76d0caaeSpatrick             if (!Inserted)
375*76d0caaeSpatrick               State.SkipWithError("Failed to insert e new element");
376*76d0caaeSpatrick           }
377*76d0caaeSpatrick #endif
378*76d0caaeSpatrick         }
379*76d0caaeSpatrick       }
380*76d0caaeSpatrick 
381*76d0caaeSpatrick       State.PauseTiming();
382*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(),
383*76d0caaeSpatrick                              Order::value == ::Order::Random ? Shuffle::Keys
384*76d0caaeSpatrick                                                              : Shuffle::None,
385*76d0caaeSpatrick                              1000);
386*76d0caaeSpatrick       State.ResumeTiming();
387*76d0caaeSpatrick     }
388*76d0caaeSpatrick   }
389*76d0caaeSpatrick 
name__anona63cc8890111::InsertAssign390*76d0caaeSpatrick   std::string name() const {
391*76d0caaeSpatrick     return "BM_InsertAssign" + baseName() + Mode::name() + Order::name();
392*76d0caaeSpatrick   }
393*76d0caaeSpatrick };
394*76d0caaeSpatrick 
395*76d0caaeSpatrick template <class Mode, class Hint>
396*76d0caaeSpatrick struct InsertAssignHint : Base {
397*76d0caaeSpatrick   using Base::Base;
398*76d0caaeSpatrick 
399*76d0caaeSpatrick   template < ::Hint hint>
400*76d0caaeSpatrick   typename std::enable_if<hint == ::Hint::Correct>::type
run__anona63cc8890111::InsertAssignHint401*76d0caaeSpatrick   run(benchmark::State& State) const {
402*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
403*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
404*76d0caaeSpatrick       for (size_t I = 0; I < Data.Maps.size(); ++I) {
405*76d0caaeSpatrick         auto& Map = Data.Maps[I];
406*76d0caaeSpatrick         auto H = Data.Hints[I].begin();
407*76d0caaeSpatrick         for (auto K : Data.Keys) {
408*76d0caaeSpatrick #ifndef VALIDATE
409*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.insert_or_assign(*H, K, 1));
410*76d0caaeSpatrick #else
411*76d0caaeSpatrick           auto Inserted = Map.insert_or_assign(*H, K, 1);
412*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
413*76d0caaeSpatrick             if (Inserted != *H)
414*76d0caaeSpatrick               State.SkipWithError("Inserted a duplicate element");
415*76d0caaeSpatrick           } else {
416*76d0caaeSpatrick             if (++Inserted != *H)
417*76d0caaeSpatrick               State.SkipWithError("Failed to insert a new element");
418*76d0caaeSpatrick           }
419*76d0caaeSpatrick #endif
420*76d0caaeSpatrick           ++H;
421*76d0caaeSpatrick         }
422*76d0caaeSpatrick       }
423*76d0caaeSpatrick 
424*76d0caaeSpatrick       State.PauseTiming();
425*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
426*76d0caaeSpatrick       State.ResumeTiming();
427*76d0caaeSpatrick     }
428*76d0caaeSpatrick   }
429*76d0caaeSpatrick 
430*76d0caaeSpatrick   template < ::Hint hint>
431*76d0caaeSpatrick   typename std::enable_if<hint != ::Hint::Correct>::type
run__anona63cc8890111::InsertAssignHint432*76d0caaeSpatrick   run(benchmark::State& State) const {
433*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
434*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
435*76d0caaeSpatrick       for (size_t I = 0; I < Data.Maps.size(); ++I) {
436*76d0caaeSpatrick         auto& Map = Data.Maps[I];
437*76d0caaeSpatrick         auto Third = *(Data.Hints[I].begin() + 2);
438*76d0caaeSpatrick         for (auto K : Data.Keys) {
439*76d0caaeSpatrick           auto Itor = hint == ::Hint::Begin
440*76d0caaeSpatrick                           ? Map.begin()
441*76d0caaeSpatrick                           : hint == ::Hint::Third ? Third : Map.end();
442*76d0caaeSpatrick #ifndef VALIDATE
443*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.insert_or_assign(Itor, K, 1));
444*76d0caaeSpatrick #else
445*76d0caaeSpatrick           size_t Size = Map.size();
446*76d0caaeSpatrick           Map.insert_or_assign(Itor, K, 1);
447*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
448*76d0caaeSpatrick             if (Size != Map.size())
449*76d0caaeSpatrick               State.SkipWithError("Inserted a duplicate element");
450*76d0caaeSpatrick           } else {
451*76d0caaeSpatrick             if (Size + 1 != Map.size())
452*76d0caaeSpatrick               State.SkipWithError("Failed to insert a new element");
453*76d0caaeSpatrick           }
454*76d0caaeSpatrick #endif
455*76d0caaeSpatrick         }
456*76d0caaeSpatrick       }
457*76d0caaeSpatrick 
458*76d0caaeSpatrick       State.PauseTiming();
459*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
460*76d0caaeSpatrick       State.ResumeTiming();
461*76d0caaeSpatrick     }
462*76d0caaeSpatrick   }
463*76d0caaeSpatrick 
run__anona63cc8890111::InsertAssignHint464*76d0caaeSpatrick   void run(benchmark::State& State) const {
465*76d0caaeSpatrick     static constexpr auto h = Hint();
466*76d0caaeSpatrick     run<h>(State);
467*76d0caaeSpatrick   }
468*76d0caaeSpatrick 
name__anona63cc8890111::InsertAssignHint469*76d0caaeSpatrick   std::string name() const {
470*76d0caaeSpatrick     return "BM_InsertAssignHint" + baseName() + Mode::name() + Hint::name();
471*76d0caaeSpatrick   }
472*76d0caaeSpatrick };
473*76d0caaeSpatrick 
474*76d0caaeSpatrick template <class Mode, class Order>
475*76d0caaeSpatrick struct Emplace : Base {
476*76d0caaeSpatrick   using Base::Base;
477*76d0caaeSpatrick 
run__anona63cc8890111::Emplace478*76d0caaeSpatrick   void run(benchmark::State& State) const {
479*76d0caaeSpatrick 
480*76d0caaeSpatrick     auto Data = makeTestingSets(
481*76d0caaeSpatrick         MapSize, Mode(),
482*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1000);
483*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
484*76d0caaeSpatrick       for (auto& Map : Data.Maps) {
485*76d0caaeSpatrick         for (auto K : Data.Keys) {
486*76d0caaeSpatrick #ifndef VALIDATE
487*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.emplace(K, 1));
488*76d0caaeSpatrick #else
489*76d0caaeSpatrick           bool Inserted = Map.emplace(K, 1).second;
490*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
491*76d0caaeSpatrick             if (Inserted)
492*76d0caaeSpatrick               State.SkipWithError("Emplaced a duplicate element");
493*76d0caaeSpatrick           } else {
494*76d0caaeSpatrick             if (!Inserted)
495*76d0caaeSpatrick               State.SkipWithError("Failed to emplace a new element");
496*76d0caaeSpatrick           }
497*76d0caaeSpatrick #endif
498*76d0caaeSpatrick         }
499*76d0caaeSpatrick       }
500*76d0caaeSpatrick 
501*76d0caaeSpatrick       State.PauseTiming();
502*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(),
503*76d0caaeSpatrick                              Order::value == ::Order::Random ? Shuffle::Keys
504*76d0caaeSpatrick                                                              : Shuffle::None,
505*76d0caaeSpatrick                              1000);
506*76d0caaeSpatrick       State.ResumeTiming();
507*76d0caaeSpatrick     }
508*76d0caaeSpatrick   }
509*76d0caaeSpatrick 
name__anona63cc8890111::Emplace510*76d0caaeSpatrick   std::string name() const {
511*76d0caaeSpatrick     return "BM_Emplace" + baseName() + Mode::name() + Order::name();
512*76d0caaeSpatrick   }
513*76d0caaeSpatrick };
514*76d0caaeSpatrick 
515*76d0caaeSpatrick template <class Mode, class Hint>
516*76d0caaeSpatrick struct EmplaceHint : Base {
517*76d0caaeSpatrick   using Base::Base;
518*76d0caaeSpatrick 
519*76d0caaeSpatrick   template < ::Hint hint>
520*76d0caaeSpatrick   typename std::enable_if<hint == ::Hint::Correct>::type
run__anona63cc8890111::EmplaceHint521*76d0caaeSpatrick   run(benchmark::State& State) const {
522*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
523*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
524*76d0caaeSpatrick       for (size_t I = 0; I < Data.Maps.size(); ++I) {
525*76d0caaeSpatrick         auto& Map = Data.Maps[I];
526*76d0caaeSpatrick         auto H = Data.Hints[I].begin();
527*76d0caaeSpatrick         for (auto K : Data.Keys) {
528*76d0caaeSpatrick #ifndef VALIDATE
529*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.emplace_hint(*H, K, 1));
530*76d0caaeSpatrick #else
531*76d0caaeSpatrick           auto Inserted = Map.emplace_hint(*H, K, 1);
532*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
533*76d0caaeSpatrick             if (Inserted != *H)
534*76d0caaeSpatrick               State.SkipWithError("Emplaced a duplicate element");
535*76d0caaeSpatrick           } else {
536*76d0caaeSpatrick             if (++Inserted != *H)
537*76d0caaeSpatrick               State.SkipWithError("Failed to emplace a new element");
538*76d0caaeSpatrick           }
539*76d0caaeSpatrick #endif
540*76d0caaeSpatrick           ++H;
541*76d0caaeSpatrick         }
542*76d0caaeSpatrick       }
543*76d0caaeSpatrick 
544*76d0caaeSpatrick       State.PauseTiming();
545*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
546*76d0caaeSpatrick       State.ResumeTiming();
547*76d0caaeSpatrick     }
548*76d0caaeSpatrick   }
549*76d0caaeSpatrick 
550*76d0caaeSpatrick   template < ::Hint hint>
551*76d0caaeSpatrick   typename std::enable_if<hint != ::Hint::Correct>::type
run__anona63cc8890111::EmplaceHint552*76d0caaeSpatrick   run(benchmark::State& State) const {
553*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
554*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
555*76d0caaeSpatrick       for (size_t I = 0; I < Data.Maps.size(); ++I) {
556*76d0caaeSpatrick         auto& Map = Data.Maps[I];
557*76d0caaeSpatrick         auto Third = *(Data.Hints[I].begin() + 2);
558*76d0caaeSpatrick         for (auto K : Data.Keys) {
559*76d0caaeSpatrick           auto Itor = hint == ::Hint::Begin
560*76d0caaeSpatrick                           ? Map.begin()
561*76d0caaeSpatrick                           : hint == ::Hint::Third ? Third : Map.end();
562*76d0caaeSpatrick #ifndef VALIDATE
563*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.emplace_hint(Itor, K, 1));
564*76d0caaeSpatrick #else
565*76d0caaeSpatrick           size_t Size = Map.size();
566*76d0caaeSpatrick           Map.emplace_hint(Itor, K, 1);
567*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
568*76d0caaeSpatrick             if (Size != Map.size())
569*76d0caaeSpatrick               State.SkipWithError("Emplaced a duplicate element");
570*76d0caaeSpatrick           } else {
571*76d0caaeSpatrick             if (Size + 1 != Map.size())
572*76d0caaeSpatrick               State.SkipWithError("Failed to emplace a new element");
573*76d0caaeSpatrick           }
574*76d0caaeSpatrick #endif
575*76d0caaeSpatrick         }
576*76d0caaeSpatrick       }
577*76d0caaeSpatrick 
578*76d0caaeSpatrick       State.PauseTiming();
579*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
580*76d0caaeSpatrick       State.ResumeTiming();
581*76d0caaeSpatrick     }
582*76d0caaeSpatrick   }
583*76d0caaeSpatrick 
run__anona63cc8890111::EmplaceHint584*76d0caaeSpatrick   void run(benchmark::State& State) const {
585*76d0caaeSpatrick     static constexpr auto h = Hint();
586*76d0caaeSpatrick     run<h>(State);
587*76d0caaeSpatrick   }
588*76d0caaeSpatrick 
name__anona63cc8890111::EmplaceHint589*76d0caaeSpatrick   std::string name() const {
590*76d0caaeSpatrick     return "BM_EmplaceHint" + baseName() + Mode::name() + Hint::name();
591*76d0caaeSpatrick   }
592*76d0caaeSpatrick };
593*76d0caaeSpatrick 
594*76d0caaeSpatrick template <class Mode, class Order>
595*76d0caaeSpatrick struct TryEmplace : Base {
596*76d0caaeSpatrick   using Base::Base;
597*76d0caaeSpatrick 
run__anona63cc8890111::TryEmplace598*76d0caaeSpatrick   void run(benchmark::State& State) const {
599*76d0caaeSpatrick 
600*76d0caaeSpatrick     auto Data = makeTestingSets(
601*76d0caaeSpatrick         MapSize, Mode(),
602*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1000);
603*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
604*76d0caaeSpatrick       for (auto& Map : Data.Maps) {
605*76d0caaeSpatrick         for (auto K : Data.Keys) {
606*76d0caaeSpatrick #ifndef VALIDATE
607*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.try_emplace(K, 1));
608*76d0caaeSpatrick #else
609*76d0caaeSpatrick           bool Inserted = Map.try_emplace(K, 1).second;
610*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
611*76d0caaeSpatrick             if (Inserted)
612*76d0caaeSpatrick               State.SkipWithError("Emplaced a duplicate element");
613*76d0caaeSpatrick           } else {
614*76d0caaeSpatrick             if (!Inserted)
615*76d0caaeSpatrick               State.SkipWithError("Failed to emplace a new element");
616*76d0caaeSpatrick           }
617*76d0caaeSpatrick #endif
618*76d0caaeSpatrick         }
619*76d0caaeSpatrick       }
620*76d0caaeSpatrick 
621*76d0caaeSpatrick       State.PauseTiming();
622*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(),
623*76d0caaeSpatrick                              Order::value == ::Order::Random ? Shuffle::Keys
624*76d0caaeSpatrick                                                              : Shuffle::None,
625*76d0caaeSpatrick                              1000);
626*76d0caaeSpatrick       State.ResumeTiming();
627*76d0caaeSpatrick     }
628*76d0caaeSpatrick   }
629*76d0caaeSpatrick 
name__anona63cc8890111::TryEmplace630*76d0caaeSpatrick   std::string name() const {
631*76d0caaeSpatrick     return "BM_TryEmplace" + baseName() + Mode::name() + Order::name();
632*76d0caaeSpatrick   }
633*76d0caaeSpatrick };
634*76d0caaeSpatrick 
635*76d0caaeSpatrick template <class Mode, class Hint>
636*76d0caaeSpatrick struct TryEmplaceHint : Base {
637*76d0caaeSpatrick   using Base::Base;
638*76d0caaeSpatrick 
639*76d0caaeSpatrick   template < ::Hint hint>
640*76d0caaeSpatrick   typename std::enable_if<hint == ::Hint::Correct>::type
run__anona63cc8890111::TryEmplaceHint641*76d0caaeSpatrick   run(benchmark::State& State) const {
642*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
643*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
644*76d0caaeSpatrick       for (size_t I = 0; I < Data.Maps.size(); ++I) {
645*76d0caaeSpatrick         auto& Map = Data.Maps[I];
646*76d0caaeSpatrick         auto H = Data.Hints[I].begin();
647*76d0caaeSpatrick         for (auto K : Data.Keys) {
648*76d0caaeSpatrick #ifndef VALIDATE
649*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.try_emplace(*H, K, 1));
650*76d0caaeSpatrick #else
651*76d0caaeSpatrick           auto Inserted = Map.try_emplace(*H, K, 1);
652*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
653*76d0caaeSpatrick             if (Inserted != *H)
654*76d0caaeSpatrick               State.SkipWithError("Emplaced a duplicate element");
655*76d0caaeSpatrick           } else {
656*76d0caaeSpatrick             if (++Inserted != *H)
657*76d0caaeSpatrick               State.SkipWithError("Failed to emplace a new element");
658*76d0caaeSpatrick           }
659*76d0caaeSpatrick #endif
660*76d0caaeSpatrick           ++H;
661*76d0caaeSpatrick         }
662*76d0caaeSpatrick       }
663*76d0caaeSpatrick 
664*76d0caaeSpatrick       State.PauseTiming();
665*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
666*76d0caaeSpatrick       State.ResumeTiming();
667*76d0caaeSpatrick     }
668*76d0caaeSpatrick   }
669*76d0caaeSpatrick 
670*76d0caaeSpatrick   template < ::Hint hint>
671*76d0caaeSpatrick   typename std::enable_if<hint != ::Hint::Correct>::type
run__anona63cc8890111::TryEmplaceHint672*76d0caaeSpatrick   run(benchmark::State& State) const {
673*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
674*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
675*76d0caaeSpatrick       for (size_t I = 0; I < Data.Maps.size(); ++I) {
676*76d0caaeSpatrick         auto& Map = Data.Maps[I];
677*76d0caaeSpatrick         auto Third = *(Data.Hints[I].begin() + 2);
678*76d0caaeSpatrick         for (auto K : Data.Keys) {
679*76d0caaeSpatrick           auto Itor = hint == ::Hint::Begin
680*76d0caaeSpatrick                           ? Map.begin()
681*76d0caaeSpatrick                           : hint == ::Hint::Third ? Third : Map.end();
682*76d0caaeSpatrick #ifndef VALIDATE
683*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.try_emplace(Itor, K, 1));
684*76d0caaeSpatrick #else
685*76d0caaeSpatrick           size_t Size = Map.size();
686*76d0caaeSpatrick           Map.try_emplace(Itor, K, 1);
687*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
688*76d0caaeSpatrick             if (Size != Map.size())
689*76d0caaeSpatrick               State.SkipWithError("Emplaced a duplicate element");
690*76d0caaeSpatrick           } else {
691*76d0caaeSpatrick             if (Size + 1 != Map.size())
692*76d0caaeSpatrick               State.SkipWithError("Failed to emplace a new element");
693*76d0caaeSpatrick           }
694*76d0caaeSpatrick #endif
695*76d0caaeSpatrick         }
696*76d0caaeSpatrick       }
697*76d0caaeSpatrick 
698*76d0caaeSpatrick       State.PauseTiming();
699*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(), Shuffle::None, 1000);
700*76d0caaeSpatrick       State.ResumeTiming();
701*76d0caaeSpatrick     }
702*76d0caaeSpatrick   }
703*76d0caaeSpatrick 
run__anona63cc8890111::TryEmplaceHint704*76d0caaeSpatrick   void run(benchmark::State& State) const {
705*76d0caaeSpatrick     static constexpr auto h = Hint();
706*76d0caaeSpatrick     run<h>(State);
707*76d0caaeSpatrick   }
708*76d0caaeSpatrick 
name__anona63cc8890111::TryEmplaceHint709*76d0caaeSpatrick   std::string name() const {
710*76d0caaeSpatrick     return "BM_TryEmplaceHint" + baseName() + Mode::name() + Hint::name();
711*76d0caaeSpatrick   }
712*76d0caaeSpatrick };
713*76d0caaeSpatrick 
714*76d0caaeSpatrick template <class Mode, class Order>
715*76d0caaeSpatrick struct Erase : Base {
716*76d0caaeSpatrick   using Base::Base;
717*76d0caaeSpatrick 
run__anona63cc8890111::Erase718*76d0caaeSpatrick   void run(benchmark::State& State) const {
719*76d0caaeSpatrick     auto Data = makeTestingSets(
720*76d0caaeSpatrick         MapSize, Mode(),
721*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1000);
722*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
723*76d0caaeSpatrick       for (auto& Map : Data.Maps) {
724*76d0caaeSpatrick         for (auto K : Data.Keys) {
725*76d0caaeSpatrick #ifndef VALIDATE
726*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.erase(K));
727*76d0caaeSpatrick #else
728*76d0caaeSpatrick           size_t I = Map.erase(K);
729*76d0caaeSpatrick           if (Mode() == ::Mode::Hit) {
730*76d0caaeSpatrick             if (I == 0)
731*76d0caaeSpatrick               State.SkipWithError("Did not find the existing element");
732*76d0caaeSpatrick           } else {
733*76d0caaeSpatrick             if (I == 1)
734*76d0caaeSpatrick               State.SkipWithError("Did find the non-existing element");
735*76d0caaeSpatrick           }
736*76d0caaeSpatrick #endif
737*76d0caaeSpatrick         }
738*76d0caaeSpatrick       }
739*76d0caaeSpatrick 
740*76d0caaeSpatrick       State.PauseTiming();
741*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode(),
742*76d0caaeSpatrick                              Order::value == ::Order::Random ? Shuffle::Keys
743*76d0caaeSpatrick                                                              : Shuffle::None,
744*76d0caaeSpatrick                              1000);
745*76d0caaeSpatrick       State.ResumeTiming();
746*76d0caaeSpatrick     }
747*76d0caaeSpatrick   }
748*76d0caaeSpatrick 
name__anona63cc8890111::Erase749*76d0caaeSpatrick   std::string name() const {
750*76d0caaeSpatrick     return "BM_Erase" + baseName() + Mode::name() + Order::name();
751*76d0caaeSpatrick   }
752*76d0caaeSpatrick };
753*76d0caaeSpatrick 
754*76d0caaeSpatrick template <class Order>
755*76d0caaeSpatrick struct EraseIterator : Base {
756*76d0caaeSpatrick   using Base::Base;
757*76d0caaeSpatrick 
run__anona63cc8890111::EraseIterator758*76d0caaeSpatrick   void run(benchmark::State& State) const {
759*76d0caaeSpatrick     auto Data = makeTestingSets(
760*76d0caaeSpatrick         MapSize, Mode::Hit,
761*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Hints : Shuffle::None, 1000);
762*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
763*76d0caaeSpatrick       for (size_t I = 0; I < Data.Maps.size(); ++I) {
764*76d0caaeSpatrick         auto& Map = Data.Maps[I];
765*76d0caaeSpatrick         for (auto H : Data.Hints[I]) {
766*76d0caaeSpatrick           benchmark::DoNotOptimize(Map.erase(H));
767*76d0caaeSpatrick         }
768*76d0caaeSpatrick #ifdef VALIDATE
769*76d0caaeSpatrick         if (!Map.empty())
770*76d0caaeSpatrick           State.SkipWithError("Did not erase the entire map");
771*76d0caaeSpatrick #endif
772*76d0caaeSpatrick       }
773*76d0caaeSpatrick 
774*76d0caaeSpatrick       State.PauseTiming();
775*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode::Hit,
776*76d0caaeSpatrick                              Order::value == ::Order::Random ? Shuffle::Hints
777*76d0caaeSpatrick                                                              : Shuffle::None,
778*76d0caaeSpatrick                              1000);
779*76d0caaeSpatrick       State.ResumeTiming();
780*76d0caaeSpatrick     }
781*76d0caaeSpatrick   }
782*76d0caaeSpatrick 
name__anona63cc8890111::EraseIterator783*76d0caaeSpatrick   std::string name() const {
784*76d0caaeSpatrick     return "BM_EraseIterator" + baseName() + Order::name();
785*76d0caaeSpatrick   }
786*76d0caaeSpatrick };
787*76d0caaeSpatrick 
788*76d0caaeSpatrick struct EraseRange : Base {
789*76d0caaeSpatrick   using Base::Base;
790*76d0caaeSpatrick 
run__anona63cc8890111::EraseRange791*76d0caaeSpatrick   void run(benchmark::State& State) const {
792*76d0caaeSpatrick     auto Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000);
793*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize * Data.Maps.size())) {
794*76d0caaeSpatrick       for (auto& Map : Data.Maps) {
795*76d0caaeSpatrick #ifndef VALIDATE
796*76d0caaeSpatrick         benchmark::DoNotOptimize(Map.erase(Map.begin(), Map.end()));
797*76d0caaeSpatrick #else
798*76d0caaeSpatrick         Map.erase(Map.begin(), Map.end());
799*76d0caaeSpatrick         if (!Map.empty())
800*76d0caaeSpatrick           State.SkipWithError("Did not erase the entire map");
801*76d0caaeSpatrick #endif
802*76d0caaeSpatrick       }
803*76d0caaeSpatrick 
804*76d0caaeSpatrick       State.PauseTiming();
805*76d0caaeSpatrick       Data = makeTestingSets(MapSize, Mode::Hit, Shuffle::None, 1000);
806*76d0caaeSpatrick       State.ResumeTiming();
807*76d0caaeSpatrick     }
808*76d0caaeSpatrick   }
809*76d0caaeSpatrick 
name__anona63cc8890111::EraseRange810*76d0caaeSpatrick   std::string name() const { return "BM_EraseRange" + baseName(); }
811*76d0caaeSpatrick };
812*76d0caaeSpatrick 
813*76d0caaeSpatrick //*******************************************************************|
814*76d0caaeSpatrick //                            Lookup                                 |
815*76d0caaeSpatrick //*******************************************************************|
816*76d0caaeSpatrick 
817*76d0caaeSpatrick template <class Mode, class Order>
818*76d0caaeSpatrick struct Count : Base {
819*76d0caaeSpatrick   using Base::Base;
820*76d0caaeSpatrick 
run__anona63cc8890111::Count821*76d0caaeSpatrick   void run(benchmark::State& State) const {
822*76d0caaeSpatrick     auto Data = makeTestingSets(
823*76d0caaeSpatrick         MapSize, Mode(),
824*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1);
825*76d0caaeSpatrick     auto& Map = Data.Maps.front();
826*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize)) {
827*76d0caaeSpatrick       for (auto K : Data.Keys) {
828*76d0caaeSpatrick #ifndef VALIDATE
829*76d0caaeSpatrick         benchmark::DoNotOptimize(Map.count(K));
830*76d0caaeSpatrick #else
831*76d0caaeSpatrick         size_t I = Map.count(K);
832*76d0caaeSpatrick         if (Mode() == ::Mode::Hit) {
833*76d0caaeSpatrick           if (I == 0)
834*76d0caaeSpatrick             State.SkipWithError("Did not find the existing element");
835*76d0caaeSpatrick         } else {
836*76d0caaeSpatrick           if (I == 1)
837*76d0caaeSpatrick             State.SkipWithError("Did find the non-existing element");
838*76d0caaeSpatrick         }
839*76d0caaeSpatrick #endif
840*76d0caaeSpatrick       }
841*76d0caaeSpatrick     }
842*76d0caaeSpatrick   }
843*76d0caaeSpatrick 
name__anona63cc8890111::Count844*76d0caaeSpatrick   std::string name() const {
845*76d0caaeSpatrick     return "BM_Count" + baseName() + Mode::name() + Order::name();
846*76d0caaeSpatrick   }
847*76d0caaeSpatrick };
848*76d0caaeSpatrick 
849*76d0caaeSpatrick template <class Mode, class Order>
850*76d0caaeSpatrick struct Find : Base {
851*76d0caaeSpatrick   using Base::Base;
852*76d0caaeSpatrick 
run__anona63cc8890111::Find853*76d0caaeSpatrick   void run(benchmark::State& State) const {
854*76d0caaeSpatrick     auto Data = makeTestingSets(
855*76d0caaeSpatrick         MapSize, Mode(),
856*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1);
857*76d0caaeSpatrick     auto& Map = Data.Maps.front();
858*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize)) {
859*76d0caaeSpatrick       for (auto K : Data.Keys) {
860*76d0caaeSpatrick #ifndef VALIDATE
861*76d0caaeSpatrick         benchmark::DoNotOptimize(Map.find(K));
862*76d0caaeSpatrick #else
863*76d0caaeSpatrick         auto Itor = Map.find(K);
864*76d0caaeSpatrick         if (Mode() == ::Mode::Hit) {
865*76d0caaeSpatrick           if (Itor == Map.end())
866*76d0caaeSpatrick             State.SkipWithError("Did not find the existing element");
867*76d0caaeSpatrick         } else {
868*76d0caaeSpatrick           if (Itor != Map.end())
869*76d0caaeSpatrick             State.SkipWithError("Did find the non-existing element");
870*76d0caaeSpatrick         }
871*76d0caaeSpatrick #endif
872*76d0caaeSpatrick       }
873*76d0caaeSpatrick     }
874*76d0caaeSpatrick   }
875*76d0caaeSpatrick 
name__anona63cc8890111::Find876*76d0caaeSpatrick   std::string name() const {
877*76d0caaeSpatrick     return "BM_Find" + baseName() + Mode::name() + Order::name();
878*76d0caaeSpatrick   }
879*76d0caaeSpatrick };
880*76d0caaeSpatrick 
881*76d0caaeSpatrick template <class Mode, class Order>
882*76d0caaeSpatrick struct EqualRange : Base {
883*76d0caaeSpatrick   using Base::Base;
884*76d0caaeSpatrick 
run__anona63cc8890111::EqualRange885*76d0caaeSpatrick   void run(benchmark::State& State) const {
886*76d0caaeSpatrick     auto Data = makeTestingSets(
887*76d0caaeSpatrick         MapSize, Mode(),
888*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1);
889*76d0caaeSpatrick     auto& Map = Data.Maps.front();
890*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize)) {
891*76d0caaeSpatrick       for (auto K : Data.Keys) {
892*76d0caaeSpatrick #ifndef VALIDATE
893*76d0caaeSpatrick         benchmark::DoNotOptimize(Map.equal_range(K));
894*76d0caaeSpatrick #else
895*76d0caaeSpatrick         auto Range = Map.equal_range(K);
896*76d0caaeSpatrick         if (Mode() == ::Mode::Hit) {
897*76d0caaeSpatrick           // Adjust validation for the last element.
898*76d0caaeSpatrick           auto Key = K;
899*76d0caaeSpatrick           if (Range.second == Map.end() && K == 2 * MapSize) {
900*76d0caaeSpatrick             --Range.second;
901*76d0caaeSpatrick             Key -= 2;
902*76d0caaeSpatrick           }
903*76d0caaeSpatrick           if (Range.first == Map.end() || Range.first->first != K ||
904*76d0caaeSpatrick               Range.second == Map.end() || Range.second->first - 2 != Key)
905*76d0caaeSpatrick             State.SkipWithError("Did not find the existing element");
906*76d0caaeSpatrick         } else {
907*76d0caaeSpatrick           if (Range.first == Map.end() || Range.first->first - 1 != K ||
908*76d0caaeSpatrick               Range.second == Map.end() || Range.second->first - 1 != K)
909*76d0caaeSpatrick             State.SkipWithError("Did find the non-existing element");
910*76d0caaeSpatrick         }
911*76d0caaeSpatrick #endif
912*76d0caaeSpatrick       }
913*76d0caaeSpatrick     }
914*76d0caaeSpatrick   }
915*76d0caaeSpatrick 
name__anona63cc8890111::EqualRange916*76d0caaeSpatrick   std::string name() const {
917*76d0caaeSpatrick     return "BM_EqualRange" + baseName() + Mode::name() + Order::name();
918*76d0caaeSpatrick   }
919*76d0caaeSpatrick };
920*76d0caaeSpatrick 
921*76d0caaeSpatrick template <class Mode, class Order>
922*76d0caaeSpatrick struct LowerBound : Base {
923*76d0caaeSpatrick   using Base::Base;
924*76d0caaeSpatrick 
run__anona63cc8890111::LowerBound925*76d0caaeSpatrick   void run(benchmark::State& State) const {
926*76d0caaeSpatrick     auto Data = makeTestingSets(
927*76d0caaeSpatrick         MapSize, Mode(),
928*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1);
929*76d0caaeSpatrick     auto& Map = Data.Maps.front();
930*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize)) {
931*76d0caaeSpatrick       for (auto K : Data.Keys) {
932*76d0caaeSpatrick #ifndef VALIDATE
933*76d0caaeSpatrick         benchmark::DoNotOptimize(Map.lower_bound(K));
934*76d0caaeSpatrick #else
935*76d0caaeSpatrick         auto Itor = Map.lower_bound(K);
936*76d0caaeSpatrick         if (Mode() == ::Mode::Hit) {
937*76d0caaeSpatrick           if (Itor == Map.end() || Itor->first != K)
938*76d0caaeSpatrick             State.SkipWithError("Did not find the existing element");
939*76d0caaeSpatrick         } else {
940*76d0caaeSpatrick           if (Itor == Map.end() || Itor->first - 1 != K)
941*76d0caaeSpatrick             State.SkipWithError("Did find the non-existing element");
942*76d0caaeSpatrick         }
943*76d0caaeSpatrick #endif
944*76d0caaeSpatrick       }
945*76d0caaeSpatrick     }
946*76d0caaeSpatrick   }
947*76d0caaeSpatrick 
name__anona63cc8890111::LowerBound948*76d0caaeSpatrick   std::string name() const {
949*76d0caaeSpatrick     return "BM_LowerBound" + baseName() + Mode::name() + Order::name();
950*76d0caaeSpatrick   }
951*76d0caaeSpatrick };
952*76d0caaeSpatrick 
953*76d0caaeSpatrick template <class Mode, class Order>
954*76d0caaeSpatrick struct UpperBound : Base {
955*76d0caaeSpatrick   using Base::Base;
956*76d0caaeSpatrick 
run__anona63cc8890111::UpperBound957*76d0caaeSpatrick   void run(benchmark::State& State) const {
958*76d0caaeSpatrick     auto Data = makeTestingSets(
959*76d0caaeSpatrick         MapSize, Mode(),
960*76d0caaeSpatrick         Order::value == ::Order::Random ? Shuffle::Keys : Shuffle::None, 1);
961*76d0caaeSpatrick     auto& Map = Data.Maps.front();
962*76d0caaeSpatrick     while (State.KeepRunningBatch(MapSize)) {
963*76d0caaeSpatrick       for (auto K : Data.Keys) {
964*76d0caaeSpatrick #ifndef VALIDATE
965*76d0caaeSpatrick         benchmark::DoNotOptimize(Map.upper_bound(K));
966*76d0caaeSpatrick #else
967*76d0caaeSpatrick         std::map<uint64_t, int64_t>::iterator Itor = Map.upper_bound(K);
968*76d0caaeSpatrick         if (Mode() == ::Mode::Hit) {
969*76d0caaeSpatrick           // Adjust validation for the last element.
970*76d0caaeSpatrick           auto Key = K;
971*76d0caaeSpatrick           if (Itor == Map.end() && K == 2 * MapSize) {
972*76d0caaeSpatrick             --Itor;
973*76d0caaeSpatrick             Key -= 2;
974*76d0caaeSpatrick           }
975*76d0caaeSpatrick           if (Itor == Map.end() || Itor->first - 2 != Key)
976*76d0caaeSpatrick             State.SkipWithError("Did not find the existing element");
977*76d0caaeSpatrick         } else {
978*76d0caaeSpatrick           if (Itor == Map.end() || Itor->first - 1 != K)
979*76d0caaeSpatrick             State.SkipWithError("Did find the non-existing element");
980*76d0caaeSpatrick         }
981*76d0caaeSpatrick #endif
982*76d0caaeSpatrick       }
983*76d0caaeSpatrick     }
984*76d0caaeSpatrick   }
985*76d0caaeSpatrick 
name__anona63cc8890111::UpperBound986*76d0caaeSpatrick   std::string name() const {
987*76d0caaeSpatrick     return "BM_UpperBound" + baseName() + Mode::name() + Order::name();
988*76d0caaeSpatrick   }
989*76d0caaeSpatrick };
990*76d0caaeSpatrick 
991*76d0caaeSpatrick } // namespace
992*76d0caaeSpatrick 
main(int argc,char ** argv)993*76d0caaeSpatrick int main(int argc, char** argv) {
994*76d0caaeSpatrick   benchmark::Initialize(&argc, argv);
995*76d0caaeSpatrick   if (benchmark::ReportUnrecognizedArguments(argc, argv))
996*76d0caaeSpatrick     return 1;
997*76d0caaeSpatrick 
998*76d0caaeSpatrick #ifdef VALIDATE
999*76d0caaeSpatrick   const std::vector<size_t> MapSize{10};
1000*76d0caaeSpatrick #else
1001*76d0caaeSpatrick   const std::vector<size_t> MapSize{10, 100, 1000, 10000, 100000, 1000000};
1002*76d0caaeSpatrick #endif
1003*76d0caaeSpatrick 
1004*76d0caaeSpatrick   // Member functions
1005*76d0caaeSpatrick   makeCartesianProductBenchmark<ConstructorDefault>();
1006*76d0caaeSpatrick   makeCartesianProductBenchmark<ConstructorIterator>(MapSize);
1007*76d0caaeSpatrick   makeCartesianProductBenchmark<ConstructorCopy>(MapSize);
1008*76d0caaeSpatrick   makeCartesianProductBenchmark<ConstructorMove>(MapSize);
1009*76d0caaeSpatrick 
1010*76d0caaeSpatrick   // Capacity
1011*76d0caaeSpatrick   makeCartesianProductBenchmark<Empty>(MapSize);
1012*76d0caaeSpatrick   makeCartesianProductBenchmark<Size>(MapSize);
1013*76d0caaeSpatrick 
1014*76d0caaeSpatrick   // Modifiers
1015*76d0caaeSpatrick   makeCartesianProductBenchmark<Clear>(MapSize);
1016*76d0caaeSpatrick   makeCartesianProductBenchmark<Insert, AllModes, AllOrders>(MapSize);
1017*76d0caaeSpatrick   makeCartesianProductBenchmark<InsertHint, AllModes, AllHints>(MapSize);
1018*76d0caaeSpatrick   makeCartesianProductBenchmark<InsertAssign, AllModes, AllOrders>(MapSize);
1019*76d0caaeSpatrick   makeCartesianProductBenchmark<InsertAssignHint, AllModes, AllHints>(MapSize);
1020*76d0caaeSpatrick 
1021*76d0caaeSpatrick   makeCartesianProductBenchmark<Emplace, AllModes, AllOrders>(MapSize);
1022*76d0caaeSpatrick   makeCartesianProductBenchmark<EmplaceHint, AllModes, AllHints>(MapSize);
1023*76d0caaeSpatrick   makeCartesianProductBenchmark<TryEmplace, AllModes, AllOrders>(MapSize);
1024*76d0caaeSpatrick   makeCartesianProductBenchmark<TryEmplaceHint, AllModes, AllHints>(MapSize);
1025*76d0caaeSpatrick   makeCartesianProductBenchmark<Erase, AllModes, AllOrders>(MapSize);
1026*76d0caaeSpatrick   makeCartesianProductBenchmark<EraseIterator, AllOrders>(MapSize);
1027*76d0caaeSpatrick   makeCartesianProductBenchmark<EraseRange>(MapSize);
1028*76d0caaeSpatrick 
1029*76d0caaeSpatrick   // Lookup
1030*76d0caaeSpatrick   makeCartesianProductBenchmark<Count, AllModes, AllOrders>(MapSize);
1031*76d0caaeSpatrick   makeCartesianProductBenchmark<Find, AllModes, AllOrders>(MapSize);
1032*76d0caaeSpatrick   makeCartesianProductBenchmark<EqualRange, AllModes, AllOrders>(MapSize);
1033*76d0caaeSpatrick   makeCartesianProductBenchmark<LowerBound, AllModes, AllOrders>(MapSize);
1034*76d0caaeSpatrick   makeCartesianProductBenchmark<UpperBound, AllModes, AllOrders>(MapSize);
1035*76d0caaeSpatrick 
1036*76d0caaeSpatrick   benchmark::RunSpecifiedBenchmarks();
1037*76d0caaeSpatrick }
1038