1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
15 #include "CartesianBenchmarks.h"
16 #include "benchmark/benchmark.h"
17 #include "test_macros.h"
19 // When VALIDATE is defined the benchmark will run to validate the benchmarks.
20 // The time taken by several operations depend on whether or not an element
21 // exists. To avoid errors in the benchmark these operations have a validation
22 // mode to test the benchmark. Since they are not meant to be benchmarked the
23 // number of sizes tested is limited to 1.
28 enum class Mode
{ Hit
, Miss
};
30 struct AllModes
: EnumValuesAsTuple
<AllModes
, Mode
, 2> {
31 static constexpr const char* Names
[] = {"ExistingElement", "NewElement"};
34 // The positions of the hints to pick:
35 // - Begin picks the first item. The item cannot be put before this element.
36 // - Thrid picks the third item. This is just an element with a valid entry
37 // before and after it.
38 // - Correct contains the correct hint.
39 // - End contains a hint to the end of the map.
40 enum class Hint
{ Begin
, Third
, Correct
, End
};
41 struct AllHints
: EnumValuesAsTuple
<AllHints
, Hint
, 4> {
42 static constexpr const char* Names
[] = {"Begin", "Third", "Correct", "End"};
45 enum class Order
{ Sorted
, Random
};
46 struct AllOrders
: EnumValuesAsTuple
<AllOrders
, Order
, 2> {
47 static constexpr const char* Names
[] = {"Sorted", "Random"};
51 std::vector
<uint64_t> Keys
;
52 std::vector
<std::map
<uint64_t, int64_t> > Maps
;
54 std::vector
<typename
std::map
<uint64_t, int64_t>::const_iterator
> >
58 enum class Shuffle
{ None
, Keys
, Hints
};
60 TestSets
makeTestingSets(size_t MapSize
, Mode mode
, Shuffle shuffle
,
63 * The shuffle does not retain the random number generator to use the same
64 * set of random numbers for every iteration.
68 int MapCount
= std::min(max_maps
, 1000000 / MapSize
);
70 for (uint64_t I
= 0; I
< MapSize
; ++I
) {
71 R
.Keys
.push_back(mode
== Mode::Hit
? 2 * I
+ 2 : 2 * I
+ 1);
73 if (shuffle
== Shuffle::Keys
)
74 std::shuffle(R
.Keys
.begin(), R
.Keys
.end(), std::mt19937());
76 for (int M
= 0; M
< MapCount
; ++M
) {
77 auto& map
= R
.Maps
.emplace_back();
78 auto& hints
= R
.Hints
.emplace_back();
79 for (uint64_t I
= 0; I
< MapSize
; ++I
) {
80 hints
.push_back(map
.insert(std::make_pair(2 * I
+ 2, 0)).first
);
82 if (shuffle
== Shuffle::Hints
)
83 std::shuffle(hints
.begin(), hints
.end(), std::mt19937());
91 Base(size_t T
) : MapSize(T
) {}
93 std::string
baseName() const { return "_MapSize=" + std::to_string(MapSize
); }
96 //*******************************************************************|
98 //*******************************************************************|
100 struct ConstructorDefault
{
101 void run(benchmark::State
& State
) const {
102 for (auto _
: State
) {
103 benchmark::DoNotOptimize(std::map
<uint64_t, int64_t>());
107 std::string
name() const { return "BM_ConstructorDefault"; }
110 struct ConstructorIterator
: Base
{
113 void run(benchmark::State
& State
) const {
114 auto Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1);
115 auto& Map
= Data
.Maps
.front();
116 while (State
.KeepRunningBatch(MapSize
)) {
118 benchmark::DoNotOptimize(
119 std::map
<uint64_t, int64_t>(Map
.begin(), Map
.end()));
121 std::map
<uint64_t, int64_t> M
{Map
.begin(), Map
.end()};
123 State
.SkipWithError("Map copy not identical");
128 std::string
name() const { return "BM_ConstructorIterator" + baseName(); }
131 struct ConstructorCopy
: Base
{
134 void run(benchmark::State
& State
) const {
135 auto Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1);
136 auto& Map
= Data
.Maps
.front();
137 while (State
.KeepRunningBatch(MapSize
)) {
139 std::map
<uint64_t, int64_t> M(Map
);
140 benchmark::DoNotOptimize(M
);
142 std::map
<uint64_t, int64_t> M(Map
);
144 State
.SkipWithError("Map copy not identical");
149 std::string
name() const { return "BM_ConstructorCopy" + baseName(); }
152 struct ConstructorMove
: Base
{
155 void run(benchmark::State
& State
) const {
156 auto Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1000);
157 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
158 for (auto& Map
: Data
.Maps
) {
159 std::map
<uint64_t, int64_t> M(std::move(Map
));
160 benchmark::DoNotOptimize(M
);
163 Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1000);
164 State
.ResumeTiming();
168 std::string
name() const { return "BM_ConstructorMove" + baseName(); }
171 //*******************************************************************|
173 //*******************************************************************|
175 struct Empty
: Base
{
178 void run(benchmark::State
& State
) const {
179 auto Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1);
180 auto& Map
= Data
.Maps
.front();
181 for (auto _
: State
) {
183 benchmark::DoNotOptimize(Map
.empty());
186 State
.SkipWithError("Map contains an invalid number of elements.");
191 std::string
name() const { return "BM_Empty" + baseName(); }
197 void run(benchmark::State
& State
) const {
198 auto Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1);
199 auto& Map
= Data
.Maps
.front();
200 for (auto _
: State
) {
202 benchmark::DoNotOptimize(Map
.size());
204 if (Map
.size() != MapSize
)
205 State
.SkipWithError("Map contains an invalid number of elements.");
210 std::string
name() const { return "BM_Size" + baseName(); }
213 //*******************************************************************|
215 //*******************************************************************|
217 struct Clear
: Base
{
220 void run(benchmark::State
& State
) const {
221 auto Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1000);
222 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
223 for (auto& Map
: Data
.Maps
) {
225 benchmark::DoNotOptimize(Map
);
228 Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1000);
229 State
.ResumeTiming();
233 std::string
name() const { return "BM_Clear" + baseName(); }
236 template <class Mode
, class Order
>
237 struct Insert
: Base
{
240 void run(benchmark::State
& State
) const {
241 auto Data
= makeTestingSets(
243 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1000);
244 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
245 for (auto& Map
: Data
.Maps
) {
246 for (auto K
: Data
.Keys
) {
248 benchmark::DoNotOptimize(Map
.insert(std::make_pair(K
, 1)));
250 bool Inserted
= Map
.insert(std::make_pair(K
, 1)).second
;
251 if (Mode() == ::Mode::Hit
) {
253 State
.SkipWithError("Inserted a duplicate element");
256 State
.SkipWithError("Failed to insert e new element");
263 Data
= makeTestingSets(MapSize
, Mode(),
264 Order::value
== ::Order::Random
? Shuffle::Keys
267 State
.ResumeTiming();
271 std::string
name() const {
272 return "BM_Insert" + baseName() + Mode::name() + Order::name();
276 template <class Mode
, class Hint
>
277 struct InsertHint
: Base
{
280 template < ::Hint hint
>
281 typename
std::enable_if
<hint
== ::Hint::Correct
>::type
282 run(benchmark::State
& State
) const {
283 auto Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
284 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
285 for (size_t I
= 0; I
< Data
.Maps
.size(); ++I
) {
286 auto& Map
= Data
.Maps
[I
];
287 auto H
= Data
.Hints
[I
].begin();
288 for (auto K
: Data
.Keys
) {
290 benchmark::DoNotOptimize(Map
.insert(*H
, std::make_pair(K
, 1)));
292 auto Inserted
= Map
.insert(*H
, std::make_pair(K
, 1));
293 if (Mode() == ::Mode::Hit
) {
295 State
.SkipWithError("Inserted a duplicate element");
297 if (++Inserted
!= *H
)
298 State
.SkipWithError("Failed to insert a new element");
306 Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
307 State
.ResumeTiming();
311 template < ::Hint hint
>
312 typename
std::enable_if
<hint
!= ::Hint::Correct
>::type
313 run(benchmark::State
& State
) const {
314 auto Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
315 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
316 for (size_t I
= 0; I
< Data
.Maps
.size(); ++I
) {
317 auto& Map
= Data
.Maps
[I
];
318 auto Third
= *(Data
.Hints
[I
].begin() + 2);
319 for (auto K
: Data
.Keys
) {
320 auto Itor
= hint
== ::Hint::Begin
322 : hint
== ::Hint::Third
? Third
: Map
.end();
324 benchmark::DoNotOptimize(Map
.insert(Itor
, std::make_pair(K
, 1)));
326 size_t Size
= Map
.size();
327 Map
.insert(Itor
, std::make_pair(K
, 1));
328 if (Mode() == ::Mode::Hit
) {
329 if (Size
!= Map
.size())
330 State
.SkipWithError("Inserted a duplicate element");
332 if (Size
+ 1 != Map
.size())
333 State
.SkipWithError("Failed to insert a new element");
340 Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
341 State
.ResumeTiming();
345 void run(benchmark::State
& State
) const {
346 static constexpr auto h
= Hint();
350 std::string
name() const {
351 return "BM_InsertHint" + baseName() + Mode::name() + Hint::name();
355 template <class Mode
, class Order
>
356 struct InsertAssign
: Base
{
359 void run(benchmark::State
& State
) const {
360 auto Data
= makeTestingSets(
362 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1000);
363 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
364 for (auto& Map
: Data
.Maps
) {
365 for (auto K
: Data
.Keys
) {
367 benchmark::DoNotOptimize(Map
.insert_or_assign(K
, 1));
369 bool Inserted
= Map
.insert_or_assign(K
, 1).second
;
370 if (Mode() == ::Mode::Hit
) {
372 State
.SkipWithError("Inserted a duplicate element");
375 State
.SkipWithError("Failed to insert e new element");
382 Data
= makeTestingSets(MapSize
, Mode(),
383 Order::value
== ::Order::Random
? Shuffle::Keys
386 State
.ResumeTiming();
390 std::string
name() const {
391 return "BM_InsertAssign" + baseName() + Mode::name() + Order::name();
395 template <class Mode
, class Hint
>
396 struct InsertAssignHint
: Base
{
399 template < ::Hint hint
>
400 typename
std::enable_if
<hint
== ::Hint::Correct
>::type
401 run(benchmark::State
& State
) const {
402 auto Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
403 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
404 for (size_t I
= 0; I
< Data
.Maps
.size(); ++I
) {
405 auto& Map
= Data
.Maps
[I
];
406 auto H
= Data
.Hints
[I
].begin();
407 for (auto K
: Data
.Keys
) {
409 benchmark::DoNotOptimize(Map
.insert_or_assign(*H
, K
, 1));
411 auto Inserted
= Map
.insert_or_assign(*H
, K
, 1);
412 if (Mode() == ::Mode::Hit
) {
414 State
.SkipWithError("Inserted a duplicate element");
416 if (++Inserted
!= *H
)
417 State
.SkipWithError("Failed to insert a new element");
425 Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
426 State
.ResumeTiming();
430 template < ::Hint hint
>
431 typename
std::enable_if
<hint
!= ::Hint::Correct
>::type
432 run(benchmark::State
& State
) const {
433 auto Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
434 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
435 for (size_t I
= 0; I
< Data
.Maps
.size(); ++I
) {
436 auto& Map
= Data
.Maps
[I
];
437 auto Third
= *(Data
.Hints
[I
].begin() + 2);
438 for (auto K
: Data
.Keys
) {
439 auto Itor
= hint
== ::Hint::Begin
441 : hint
== ::Hint::Third
? Third
: Map
.end();
443 benchmark::DoNotOptimize(Map
.insert_or_assign(Itor
, K
, 1));
445 size_t Size
= Map
.size();
446 Map
.insert_or_assign(Itor
, K
, 1);
447 if (Mode() == ::Mode::Hit
) {
448 if (Size
!= Map
.size())
449 State
.SkipWithError("Inserted a duplicate element");
451 if (Size
+ 1 != Map
.size())
452 State
.SkipWithError("Failed to insert a new element");
459 Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
460 State
.ResumeTiming();
464 void run(benchmark::State
& State
) const {
465 static constexpr auto h
= Hint();
469 std::string
name() const {
470 return "BM_InsertAssignHint" + baseName() + Mode::name() + Hint::name();
474 template <class Mode
, class Order
>
475 struct Emplace
: Base
{
478 void run(benchmark::State
& State
) const {
480 auto Data
= makeTestingSets(
482 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1000);
483 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
484 for (auto& Map
: Data
.Maps
) {
485 for (auto K
: Data
.Keys
) {
487 benchmark::DoNotOptimize(Map
.emplace(K
, 1));
489 bool Inserted
= Map
.emplace(K
, 1).second
;
490 if (Mode() == ::Mode::Hit
) {
492 State
.SkipWithError("Emplaced a duplicate element");
495 State
.SkipWithError("Failed to emplace a new element");
502 Data
= makeTestingSets(MapSize
, Mode(),
503 Order::value
== ::Order::Random
? Shuffle::Keys
506 State
.ResumeTiming();
510 std::string
name() const {
511 return "BM_Emplace" + baseName() + Mode::name() + Order::name();
515 template <class Mode
, class Hint
>
516 struct EmplaceHint
: Base
{
519 template < ::Hint hint
>
520 typename
std::enable_if
<hint
== ::Hint::Correct
>::type
521 run(benchmark::State
& State
) const {
522 auto Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
523 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
524 for (size_t I
= 0; I
< Data
.Maps
.size(); ++I
) {
525 auto& Map
= Data
.Maps
[I
];
526 auto H
= Data
.Hints
[I
].begin();
527 for (auto K
: Data
.Keys
) {
529 benchmark::DoNotOptimize(Map
.emplace_hint(*H
, K
, 1));
531 auto Inserted
= Map
.emplace_hint(*H
, K
, 1);
532 if (Mode() == ::Mode::Hit
) {
534 State
.SkipWithError("Emplaced a duplicate element");
536 if (++Inserted
!= *H
)
537 State
.SkipWithError("Failed to emplace a new element");
545 Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
546 State
.ResumeTiming();
550 template < ::Hint hint
>
551 typename
std::enable_if
<hint
!= ::Hint::Correct
>::type
552 run(benchmark::State
& State
) const {
553 auto Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
554 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
555 for (size_t I
= 0; I
< Data
.Maps
.size(); ++I
) {
556 auto& Map
= Data
.Maps
[I
];
557 auto Third
= *(Data
.Hints
[I
].begin() + 2);
558 for (auto K
: Data
.Keys
) {
559 auto Itor
= hint
== ::Hint::Begin
561 : hint
== ::Hint::Third
? Third
: Map
.end();
563 benchmark::DoNotOptimize(Map
.emplace_hint(Itor
, K
, 1));
565 size_t Size
= Map
.size();
566 Map
.emplace_hint(Itor
, K
, 1);
567 if (Mode() == ::Mode::Hit
) {
568 if (Size
!= Map
.size())
569 State
.SkipWithError("Emplaced a duplicate element");
571 if (Size
+ 1 != Map
.size())
572 State
.SkipWithError("Failed to emplace a new element");
579 Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
580 State
.ResumeTiming();
584 void run(benchmark::State
& State
) const {
585 static constexpr auto h
= Hint();
589 std::string
name() const {
590 return "BM_EmplaceHint" + baseName() + Mode::name() + Hint::name();
594 template <class Mode
, class Order
>
595 struct TryEmplace
: Base
{
598 void run(benchmark::State
& State
) const {
600 auto Data
= makeTestingSets(
602 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1000);
603 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
604 for (auto& Map
: Data
.Maps
) {
605 for (auto K
: Data
.Keys
) {
607 benchmark::DoNotOptimize(Map
.try_emplace(K
, 1));
609 bool Inserted
= Map
.try_emplace(K
, 1).second
;
610 if (Mode() == ::Mode::Hit
) {
612 State
.SkipWithError("Emplaced a duplicate element");
615 State
.SkipWithError("Failed to emplace a new element");
622 Data
= makeTestingSets(MapSize
, Mode(),
623 Order::value
== ::Order::Random
? Shuffle::Keys
626 State
.ResumeTiming();
630 std::string
name() const {
631 return "BM_TryEmplace" + baseName() + Mode::name() + Order::name();
635 template <class Mode
, class Hint
>
636 struct TryEmplaceHint
: Base
{
639 template < ::Hint hint
>
640 typename
std::enable_if
<hint
== ::Hint::Correct
>::type
641 run(benchmark::State
& State
) const {
642 auto Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
643 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
644 for (size_t I
= 0; I
< Data
.Maps
.size(); ++I
) {
645 auto& Map
= Data
.Maps
[I
];
646 auto H
= Data
.Hints
[I
].begin();
647 for (auto K
: Data
.Keys
) {
649 benchmark::DoNotOptimize(Map
.try_emplace(*H
, K
, 1));
651 auto Inserted
= Map
.try_emplace(*H
, K
, 1);
652 if (Mode() == ::Mode::Hit
) {
654 State
.SkipWithError("Emplaced a duplicate element");
656 if (++Inserted
!= *H
)
657 State
.SkipWithError("Failed to emplace a new element");
665 Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
666 State
.ResumeTiming();
670 template < ::Hint hint
>
671 typename
std::enable_if
<hint
!= ::Hint::Correct
>::type
672 run(benchmark::State
& State
) const {
673 auto Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
674 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
675 for (size_t I
= 0; I
< Data
.Maps
.size(); ++I
) {
676 auto& Map
= Data
.Maps
[I
];
677 auto Third
= *(Data
.Hints
[I
].begin() + 2);
678 for (auto K
: Data
.Keys
) {
679 auto Itor
= hint
== ::Hint::Begin
681 : hint
== ::Hint::Third
? Third
: Map
.end();
683 benchmark::DoNotOptimize(Map
.try_emplace(Itor
, K
, 1));
685 size_t Size
= Map
.size();
686 Map
.try_emplace(Itor
, K
, 1);
687 if (Mode() == ::Mode::Hit
) {
688 if (Size
!= Map
.size())
689 State
.SkipWithError("Emplaced a duplicate element");
691 if (Size
+ 1 != Map
.size())
692 State
.SkipWithError("Failed to emplace a new element");
699 Data
= makeTestingSets(MapSize
, Mode(), Shuffle::None
, 1000);
700 State
.ResumeTiming();
704 void run(benchmark::State
& State
) const {
705 static constexpr auto h
= Hint();
709 std::string
name() const {
710 return "BM_TryEmplaceHint" + baseName() + Mode::name() + Hint::name();
714 template <class Mode
, class Order
>
715 struct Erase
: Base
{
718 void run(benchmark::State
& State
) const {
719 auto Data
= makeTestingSets(
721 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1000);
722 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
723 for (auto& Map
: Data
.Maps
) {
724 for (auto K
: Data
.Keys
) {
726 benchmark::DoNotOptimize(Map
.erase(K
));
728 size_t I
= Map
.erase(K
);
729 if (Mode() == ::Mode::Hit
) {
731 State
.SkipWithError("Did not find the existing element");
734 State
.SkipWithError("Did find the non-existing element");
741 Data
= makeTestingSets(MapSize
, Mode(),
742 Order::value
== ::Order::Random
? Shuffle::Keys
745 State
.ResumeTiming();
749 std::string
name() const {
750 return "BM_Erase" + baseName() + Mode::name() + Order::name();
754 template <class Order
>
755 struct EraseIterator
: Base
{
758 void run(benchmark::State
& State
) const {
759 auto Data
= makeTestingSets(
761 Order::value
== ::Order::Random
? Shuffle::Hints
: Shuffle::None
, 1000);
762 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
763 for (size_t I
= 0; I
< Data
.Maps
.size(); ++I
) {
764 auto& Map
= Data
.Maps
[I
];
765 for (auto H
: Data
.Hints
[I
]) {
766 benchmark::DoNotOptimize(Map
.erase(H
));
770 State
.SkipWithError("Did not erase the entire map");
775 Data
= makeTestingSets(MapSize
, Mode::Hit
,
776 Order::value
== ::Order::Random
? Shuffle::Hints
779 State
.ResumeTiming();
783 std::string
name() const {
784 return "BM_EraseIterator" + baseName() + Order::name();
788 struct EraseRange
: Base
{
791 void run(benchmark::State
& State
) const {
792 auto Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1000);
793 while (State
.KeepRunningBatch(MapSize
* Data
.Maps
.size())) {
794 for (auto& Map
: Data
.Maps
) {
796 benchmark::DoNotOptimize(Map
.erase(Map
.begin(), Map
.end()));
798 Map
.erase(Map
.begin(), Map
.end());
800 State
.SkipWithError("Did not erase the entire map");
805 Data
= makeTestingSets(MapSize
, Mode::Hit
, Shuffle::None
, 1000);
806 State
.ResumeTiming();
810 std::string
name() const { return "BM_EraseRange" + baseName(); }
813 //*******************************************************************|
815 //*******************************************************************|
817 template <class Mode
, class Order
>
818 struct Count
: Base
{
821 void run(benchmark::State
& State
) const {
822 auto Data
= makeTestingSets(
824 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1);
825 auto& Map
= Data
.Maps
.front();
826 while (State
.KeepRunningBatch(MapSize
)) {
827 for (auto K
: Data
.Keys
) {
829 benchmark::DoNotOptimize(Map
.count(K
));
831 size_t I
= Map
.count(K
);
832 if (Mode() == ::Mode::Hit
) {
834 State
.SkipWithError("Did not find the existing element");
837 State
.SkipWithError("Did find the non-existing element");
844 std::string
name() const {
845 return "BM_Count" + baseName() + Mode::name() + Order::name();
849 template <class Mode
, class Order
>
853 void run(benchmark::State
& State
) const {
854 auto Data
= makeTestingSets(
856 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1);
857 auto& Map
= Data
.Maps
.front();
858 while (State
.KeepRunningBatch(MapSize
)) {
859 for (auto K
: Data
.Keys
) {
861 benchmark::DoNotOptimize(Map
.find(K
));
863 auto Itor
= Map
.find(K
);
864 if (Mode() == ::Mode::Hit
) {
865 if (Itor
== Map
.end())
866 State
.SkipWithError("Did not find the existing element");
868 if (Itor
!= Map
.end())
869 State
.SkipWithError("Did find the non-existing element");
876 std::string
name() const {
877 return "BM_Find" + baseName() + Mode::name() + Order::name();
881 template <class Mode
, class Order
>
882 struct EqualRange
: Base
{
885 void run(benchmark::State
& State
) const {
886 auto Data
= makeTestingSets(
888 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1);
889 auto& Map
= Data
.Maps
.front();
890 while (State
.KeepRunningBatch(MapSize
)) {
891 for (auto K
: Data
.Keys
) {
893 benchmark::DoNotOptimize(Map
.equal_range(K
));
895 auto Range
= Map
.equal_range(K
);
896 if (Mode() == ::Mode::Hit
) {
897 // Adjust validation for the last element.
899 if (Range
.second
== Map
.end() && K
== 2 * MapSize
) {
903 if (Range
.first
== Map
.end() || Range
.first
->first
!= K
||
904 Range
.second
== Map
.end() || Range
.second
->first
- 2 != Key
)
905 State
.SkipWithError("Did not find the existing element");
907 if (Range
.first
== Map
.end() || Range
.first
->first
- 1 != K
||
908 Range
.second
== Map
.end() || Range
.second
->first
- 1 != K
)
909 State
.SkipWithError("Did find the non-existing element");
916 std::string
name() const {
917 return "BM_EqualRange" + baseName() + Mode::name() + Order::name();
921 template <class Mode
, class Order
>
922 struct LowerBound
: Base
{
925 void run(benchmark::State
& State
) const {
926 auto Data
= makeTestingSets(
928 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1);
929 auto& Map
= Data
.Maps
.front();
930 while (State
.KeepRunningBatch(MapSize
)) {
931 for (auto K
: Data
.Keys
) {
933 benchmark::DoNotOptimize(Map
.lower_bound(K
));
935 auto Itor
= Map
.lower_bound(K
);
936 if (Mode() == ::Mode::Hit
) {
937 if (Itor
== Map
.end() || Itor
->first
!= K
)
938 State
.SkipWithError("Did not find the existing element");
940 if (Itor
== Map
.end() || Itor
->first
- 1 != K
)
941 State
.SkipWithError("Did find the non-existing element");
948 std::string
name() const {
949 return "BM_LowerBound" + baseName() + Mode::name() + Order::name();
953 template <class Mode
, class Order
>
954 struct UpperBound
: Base
{
957 void run(benchmark::State
& State
) const {
958 auto Data
= makeTestingSets(
960 Order::value
== ::Order::Random
? Shuffle::Keys
: Shuffle::None
, 1);
961 auto& Map
= Data
.Maps
.front();
962 while (State
.KeepRunningBatch(MapSize
)) {
963 for (auto K
: Data
.Keys
) {
965 benchmark::DoNotOptimize(Map
.upper_bound(K
));
967 std::map
<uint64_t, int64_t>::iterator Itor
= Map
.upper_bound(K
);
968 if (Mode() == ::Mode::Hit
) {
969 // Adjust validation for the last element.
971 if (Itor
== Map
.end() && K
== 2 * MapSize
) {
975 if (Itor
== Map
.end() || Itor
->first
- 2 != Key
)
976 State
.SkipWithError("Did not find the existing element");
978 if (Itor
== Map
.end() || Itor
->first
- 1 != K
)
979 State
.SkipWithError("Did find the non-existing element");
986 std::string
name() const {
987 return "BM_UpperBound" + baseName() + Mode::name() + Order::name();
993 int main(int argc
, char** argv
) {
994 benchmark::Initialize(&argc
, argv
);
995 if (benchmark::ReportUnrecognizedArguments(argc
, argv
))
999 const std::vector
<size_t> MapSize
{10};
1001 const std::vector
<size_t> MapSize
{10, 100, 1000, 10000, 100000, 1000000};
1005 makeCartesianProductBenchmark
<ConstructorDefault
>();
1006 makeCartesianProductBenchmark
<ConstructorIterator
>(MapSize
);
1007 makeCartesianProductBenchmark
<ConstructorCopy
>(MapSize
);
1008 makeCartesianProductBenchmark
<ConstructorMove
>(MapSize
);
1011 makeCartesianProductBenchmark
<Empty
>(MapSize
);
1012 makeCartesianProductBenchmark
<Size
>(MapSize
);
1015 makeCartesianProductBenchmark
<Clear
>(MapSize
);
1016 makeCartesianProductBenchmark
<Insert
, AllModes
, AllOrders
>(MapSize
);
1017 makeCartesianProductBenchmark
<InsertHint
, AllModes
, AllHints
>(MapSize
);
1018 makeCartesianProductBenchmark
<InsertAssign
, AllModes
, AllOrders
>(MapSize
);
1019 makeCartesianProductBenchmark
<InsertAssignHint
, AllModes
, AllHints
>(MapSize
);
1021 makeCartesianProductBenchmark
<Emplace
, AllModes
, AllOrders
>(MapSize
);
1022 makeCartesianProductBenchmark
<EmplaceHint
, AllModes
, AllHints
>(MapSize
);
1023 makeCartesianProductBenchmark
<TryEmplace
, AllModes
, AllOrders
>(MapSize
);
1024 makeCartesianProductBenchmark
<TryEmplaceHint
, AllModes
, AllHints
>(MapSize
);
1025 makeCartesianProductBenchmark
<Erase
, AllModes
, AllOrders
>(MapSize
);
1026 makeCartesianProductBenchmark
<EraseIterator
, AllOrders
>(MapSize
);
1027 makeCartesianProductBenchmark
<EraseRange
>(MapSize
);
1030 makeCartesianProductBenchmark
<Count
, AllModes
, AllOrders
>(MapSize
);
1031 makeCartesianProductBenchmark
<Find
, AllModes
, AllOrders
>(MapSize
);
1032 makeCartesianProductBenchmark
<EqualRange
, AllModes
, AllOrders
>(MapSize
);
1033 makeCartesianProductBenchmark
<LowerBound
, AllModes
, AllOrders
>(MapSize
);
1034 makeCartesianProductBenchmark
<UpperBound
, AllModes
, AllOrders
>(MapSize
);
1036 benchmark::RunSpecifiedBenchmarks();