1*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2*58b9f456SAndroid Build Coastguard Worker //
3*58b9f456SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*58b9f456SAndroid Build Coastguard Worker //
5*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*58b9f456SAndroid Build Coastguard Worker //
8*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*58b9f456SAndroid Build Coastguard Worker
10*58b9f456SAndroid Build Coastguard Worker #include <algorithm>
11*58b9f456SAndroid Build Coastguard Worker #include <cstdint>
12*58b9f456SAndroid Build Coastguard Worker #include <memory>
13*58b9f456SAndroid Build Coastguard Worker #include <random>
14*58b9f456SAndroid Build Coastguard Worker #include <set>
15*58b9f456SAndroid Build Coastguard Worker #include <string>
16*58b9f456SAndroid Build Coastguard Worker #include <vector>
17*58b9f456SAndroid Build Coastguard Worker
18*58b9f456SAndroid Build Coastguard Worker #include "CartesianBenchmarks.hpp"
19*58b9f456SAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
20*58b9f456SAndroid Build Coastguard Worker #include "test_macros.h"
21*58b9f456SAndroid Build Coastguard Worker
22*58b9f456SAndroid Build Coastguard Worker namespace {
23*58b9f456SAndroid Build Coastguard Worker
24*58b9f456SAndroid Build Coastguard Worker enum class HitType { Hit, Miss };
25*58b9f456SAndroid Build Coastguard Worker
26*58b9f456SAndroid Build Coastguard Worker struct AllHitTypes : EnumValuesAsTuple<AllHitTypes, HitType, 2> {
27*58b9f456SAndroid Build Coastguard Worker static constexpr const char* Names[] = {"Hit", "Miss"};
28*58b9f456SAndroid Build Coastguard Worker };
29*58b9f456SAndroid Build Coastguard Worker
30*58b9f456SAndroid Build Coastguard Worker enum class AccessPattern { Ordered, Random };
31*58b9f456SAndroid Build Coastguard Worker
32*58b9f456SAndroid Build Coastguard Worker struct AllAccessPattern
33*58b9f456SAndroid Build Coastguard Worker : EnumValuesAsTuple<AllAccessPattern, AccessPattern, 2> {
34*58b9f456SAndroid Build Coastguard Worker static constexpr const char* Names[] = {"Ordered", "Random"};
35*58b9f456SAndroid Build Coastguard Worker };
36*58b9f456SAndroid Build Coastguard Worker
sortKeysBy(std::vector<uint64_t> & Keys,AccessPattern AP)37*58b9f456SAndroid Build Coastguard Worker void sortKeysBy(std::vector<uint64_t>& Keys, AccessPattern AP) {
38*58b9f456SAndroid Build Coastguard Worker if (AP == AccessPattern::Random) {
39*58b9f456SAndroid Build Coastguard Worker std::random_device R;
40*58b9f456SAndroid Build Coastguard Worker std::mt19937 M(R());
41*58b9f456SAndroid Build Coastguard Worker std::shuffle(std::begin(Keys), std::end(Keys), M);
42*58b9f456SAndroid Build Coastguard Worker }
43*58b9f456SAndroid Build Coastguard Worker }
44*58b9f456SAndroid Build Coastguard Worker
45*58b9f456SAndroid Build Coastguard Worker struct TestSets {
46*58b9f456SAndroid Build Coastguard Worker std::vector<std::set<uint64_t> > Sets;
47*58b9f456SAndroid Build Coastguard Worker std::vector<uint64_t> Keys;
48*58b9f456SAndroid Build Coastguard Worker };
49*58b9f456SAndroid Build Coastguard Worker
makeTestingSets(size_t TableSize,size_t NumTables,HitType Hit,AccessPattern Access)50*58b9f456SAndroid Build Coastguard Worker TestSets makeTestingSets(size_t TableSize, size_t NumTables, HitType Hit,
51*58b9f456SAndroid Build Coastguard Worker AccessPattern Access) {
52*58b9f456SAndroid Build Coastguard Worker TestSets R;
53*58b9f456SAndroid Build Coastguard Worker R.Sets.resize(1);
54*58b9f456SAndroid Build Coastguard Worker
55*58b9f456SAndroid Build Coastguard Worker for (uint64_t I = 0; I < TableSize; ++I) {
56*58b9f456SAndroid Build Coastguard Worker R.Sets[0].insert(2 * I);
57*58b9f456SAndroid Build Coastguard Worker R.Keys.push_back(Hit == HitType::Hit ? 2 * I : 2 * I + 1);
58*58b9f456SAndroid Build Coastguard Worker }
59*58b9f456SAndroid Build Coastguard Worker R.Sets.resize(NumTables, R.Sets[0]);
60*58b9f456SAndroid Build Coastguard Worker sortKeysBy(R.Keys, Access);
61*58b9f456SAndroid Build Coastguard Worker
62*58b9f456SAndroid Build Coastguard Worker return R;
63*58b9f456SAndroid Build Coastguard Worker }
64*58b9f456SAndroid Build Coastguard Worker
65*58b9f456SAndroid Build Coastguard Worker struct Base {
66*58b9f456SAndroid Build Coastguard Worker size_t TableSize;
67*58b9f456SAndroid Build Coastguard Worker size_t NumTables;
Base__anonfb3b86bc0111::Base68*58b9f456SAndroid Build Coastguard Worker Base(size_t T, size_t N) : TableSize(T), NumTables(N) {}
69*58b9f456SAndroid Build Coastguard Worker
skip__anonfb3b86bc0111::Base70*58b9f456SAndroid Build Coastguard Worker bool skip() const {
71*58b9f456SAndroid Build Coastguard Worker size_t Total = TableSize * NumTables;
72*58b9f456SAndroid Build Coastguard Worker return Total < 100 || Total > 1000000;
73*58b9f456SAndroid Build Coastguard Worker }
74*58b9f456SAndroid Build Coastguard Worker
baseName__anonfb3b86bc0111::Base75*58b9f456SAndroid Build Coastguard Worker std::string baseName() const {
76*58b9f456SAndroid Build Coastguard Worker return "_TableSize" + std::to_string(TableSize) + "_NumTables" +
77*58b9f456SAndroid Build Coastguard Worker std::to_string(NumTables);
78*58b9f456SAndroid Build Coastguard Worker }
79*58b9f456SAndroid Build Coastguard Worker };
80*58b9f456SAndroid Build Coastguard Worker
81*58b9f456SAndroid Build Coastguard Worker template <class Access>
82*58b9f456SAndroid Build Coastguard Worker struct Create : Base {
83*58b9f456SAndroid Build Coastguard Worker using Base::Base;
84*58b9f456SAndroid Build Coastguard Worker
run__anonfb3b86bc0111::Create85*58b9f456SAndroid Build Coastguard Worker void run(benchmark::State& State) const {
86*58b9f456SAndroid Build Coastguard Worker std::vector<uint64_t> Keys(TableSize);
87*58b9f456SAndroid Build Coastguard Worker std::iota(Keys.begin(), Keys.end(), uint64_t{0});
88*58b9f456SAndroid Build Coastguard Worker sortKeysBy(Keys, Access());
89*58b9f456SAndroid Build Coastguard Worker
90*58b9f456SAndroid Build Coastguard Worker while (State.KeepRunningBatch(TableSize * NumTables)) {
91*58b9f456SAndroid Build Coastguard Worker std::vector<std::set<uint64_t>> Sets(NumTables);
92*58b9f456SAndroid Build Coastguard Worker for (auto K : Keys) {
93*58b9f456SAndroid Build Coastguard Worker for (auto& Set : Sets) {
94*58b9f456SAndroid Build Coastguard Worker benchmark::DoNotOptimize(Set.insert(K));
95*58b9f456SAndroid Build Coastguard Worker }
96*58b9f456SAndroid Build Coastguard Worker }
97*58b9f456SAndroid Build Coastguard Worker }
98*58b9f456SAndroid Build Coastguard Worker }
99*58b9f456SAndroid Build Coastguard Worker
name__anonfb3b86bc0111::Create100*58b9f456SAndroid Build Coastguard Worker std::string name() const {
101*58b9f456SAndroid Build Coastguard Worker return "BM_Create" + Access::name() + baseName();
102*58b9f456SAndroid Build Coastguard Worker }
103*58b9f456SAndroid Build Coastguard Worker };
104*58b9f456SAndroid Build Coastguard Worker
105*58b9f456SAndroid Build Coastguard Worker template <class Hit, class Access>
106*58b9f456SAndroid Build Coastguard Worker struct Find : Base {
107*58b9f456SAndroid Build Coastguard Worker using Base::Base;
108*58b9f456SAndroid Build Coastguard Worker
run__anonfb3b86bc0111::Find109*58b9f456SAndroid Build Coastguard Worker void run(benchmark::State& State) const {
110*58b9f456SAndroid Build Coastguard Worker auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
111*58b9f456SAndroid Build Coastguard Worker
112*58b9f456SAndroid Build Coastguard Worker while (State.KeepRunningBatch(TableSize * NumTables)) {
113*58b9f456SAndroid Build Coastguard Worker for (auto K : Data.Keys) {
114*58b9f456SAndroid Build Coastguard Worker for (auto& Set : Data.Sets) {
115*58b9f456SAndroid Build Coastguard Worker benchmark::DoNotOptimize(Set.find(K));
116*58b9f456SAndroid Build Coastguard Worker }
117*58b9f456SAndroid Build Coastguard Worker }
118*58b9f456SAndroid Build Coastguard Worker }
119*58b9f456SAndroid Build Coastguard Worker }
120*58b9f456SAndroid Build Coastguard Worker
name__anonfb3b86bc0111::Find121*58b9f456SAndroid Build Coastguard Worker std::string name() const {
122*58b9f456SAndroid Build Coastguard Worker return "BM_Find" + Hit::name() + Access::name() + baseName();
123*58b9f456SAndroid Build Coastguard Worker }
124*58b9f456SAndroid Build Coastguard Worker };
125*58b9f456SAndroid Build Coastguard Worker
126*58b9f456SAndroid Build Coastguard Worker template <class Hit, class Access>
127*58b9f456SAndroid Build Coastguard Worker struct FindNeEnd : Base {
128*58b9f456SAndroid Build Coastguard Worker using Base::Base;
129*58b9f456SAndroid Build Coastguard Worker
run__anonfb3b86bc0111::FindNeEnd130*58b9f456SAndroid Build Coastguard Worker void run(benchmark::State& State) const {
131*58b9f456SAndroid Build Coastguard Worker auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
132*58b9f456SAndroid Build Coastguard Worker
133*58b9f456SAndroid Build Coastguard Worker while (State.KeepRunningBatch(TableSize * NumTables)) {
134*58b9f456SAndroid Build Coastguard Worker for (auto K : Data.Keys) {
135*58b9f456SAndroid Build Coastguard Worker for (auto& Set : Data.Sets) {
136*58b9f456SAndroid Build Coastguard Worker benchmark::DoNotOptimize(Set.find(K) != Set.end());
137*58b9f456SAndroid Build Coastguard Worker }
138*58b9f456SAndroid Build Coastguard Worker }
139*58b9f456SAndroid Build Coastguard Worker }
140*58b9f456SAndroid Build Coastguard Worker }
141*58b9f456SAndroid Build Coastguard Worker
name__anonfb3b86bc0111::FindNeEnd142*58b9f456SAndroid Build Coastguard Worker std::string name() const {
143*58b9f456SAndroid Build Coastguard Worker return "BM_FindNeEnd" + Hit::name() + Access::name() + baseName();
144*58b9f456SAndroid Build Coastguard Worker }
145*58b9f456SAndroid Build Coastguard Worker };
146*58b9f456SAndroid Build Coastguard Worker
147*58b9f456SAndroid Build Coastguard Worker template <class Access>
148*58b9f456SAndroid Build Coastguard Worker struct InsertHit : Base {
149*58b9f456SAndroid Build Coastguard Worker using Base::Base;
150*58b9f456SAndroid Build Coastguard Worker
run__anonfb3b86bc0111::InsertHit151*58b9f456SAndroid Build Coastguard Worker void run(benchmark::State& State) const {
152*58b9f456SAndroid Build Coastguard Worker auto Data = makeTestingSets(TableSize, NumTables, HitType::Hit, Access());
153*58b9f456SAndroid Build Coastguard Worker
154*58b9f456SAndroid Build Coastguard Worker while (State.KeepRunningBatch(TableSize * NumTables)) {
155*58b9f456SAndroid Build Coastguard Worker for (auto K : Data.Keys) {
156*58b9f456SAndroid Build Coastguard Worker for (auto& Set : Data.Sets) {
157*58b9f456SAndroid Build Coastguard Worker benchmark::DoNotOptimize(Set.insert(K));
158*58b9f456SAndroid Build Coastguard Worker }
159*58b9f456SAndroid Build Coastguard Worker }
160*58b9f456SAndroid Build Coastguard Worker }
161*58b9f456SAndroid Build Coastguard Worker }
162*58b9f456SAndroid Build Coastguard Worker
name__anonfb3b86bc0111::InsertHit163*58b9f456SAndroid Build Coastguard Worker std::string name() const {
164*58b9f456SAndroid Build Coastguard Worker return "BM_InsertHit" + Access::name() + baseName();
165*58b9f456SAndroid Build Coastguard Worker }
166*58b9f456SAndroid Build Coastguard Worker };
167*58b9f456SAndroid Build Coastguard Worker
168*58b9f456SAndroid Build Coastguard Worker template <class Access>
169*58b9f456SAndroid Build Coastguard Worker struct InsertMissAndErase : Base {
170*58b9f456SAndroid Build Coastguard Worker using Base::Base;
171*58b9f456SAndroid Build Coastguard Worker
run__anonfb3b86bc0111::InsertMissAndErase172*58b9f456SAndroid Build Coastguard Worker void run(benchmark::State& State) const {
173*58b9f456SAndroid Build Coastguard Worker auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss, Access());
174*58b9f456SAndroid Build Coastguard Worker
175*58b9f456SAndroid Build Coastguard Worker while (State.KeepRunningBatch(TableSize * NumTables)) {
176*58b9f456SAndroid Build Coastguard Worker for (auto K : Data.Keys) {
177*58b9f456SAndroid Build Coastguard Worker for (auto& Set : Data.Sets) {
178*58b9f456SAndroid Build Coastguard Worker benchmark::DoNotOptimize(Set.erase(Set.insert(K).first));
179*58b9f456SAndroid Build Coastguard Worker }
180*58b9f456SAndroid Build Coastguard Worker }
181*58b9f456SAndroid Build Coastguard Worker }
182*58b9f456SAndroid Build Coastguard Worker }
183*58b9f456SAndroid Build Coastguard Worker
name__anonfb3b86bc0111::InsertMissAndErase184*58b9f456SAndroid Build Coastguard Worker std::string name() const {
185*58b9f456SAndroid Build Coastguard Worker return "BM_InsertMissAndErase" + Access::name() + baseName();
186*58b9f456SAndroid Build Coastguard Worker }
187*58b9f456SAndroid Build Coastguard Worker };
188*58b9f456SAndroid Build Coastguard Worker
189*58b9f456SAndroid Build Coastguard Worker struct IterateRangeFor : Base {
190*58b9f456SAndroid Build Coastguard Worker using Base::Base;
191*58b9f456SAndroid Build Coastguard Worker
run__anonfb3b86bc0111::IterateRangeFor192*58b9f456SAndroid Build Coastguard Worker void run(benchmark::State& State) const {
193*58b9f456SAndroid Build Coastguard Worker auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
194*58b9f456SAndroid Build Coastguard Worker AccessPattern::Ordered);
195*58b9f456SAndroid Build Coastguard Worker
196*58b9f456SAndroid Build Coastguard Worker while (State.KeepRunningBatch(TableSize * NumTables)) {
197*58b9f456SAndroid Build Coastguard Worker for (auto& Set : Data.Sets) {
198*58b9f456SAndroid Build Coastguard Worker for (auto& V : Set) {
199*58b9f456SAndroid Build Coastguard Worker benchmark::DoNotOptimize(V);
200*58b9f456SAndroid Build Coastguard Worker }
201*58b9f456SAndroid Build Coastguard Worker }
202*58b9f456SAndroid Build Coastguard Worker }
203*58b9f456SAndroid Build Coastguard Worker }
204*58b9f456SAndroid Build Coastguard Worker
name__anonfb3b86bc0111::IterateRangeFor205*58b9f456SAndroid Build Coastguard Worker std::string name() const { return "BM_IterateRangeFor" + baseName(); }
206*58b9f456SAndroid Build Coastguard Worker };
207*58b9f456SAndroid Build Coastguard Worker
208*58b9f456SAndroid Build Coastguard Worker struct IterateBeginEnd : Base {
209*58b9f456SAndroid Build Coastguard Worker using Base::Base;
210*58b9f456SAndroid Build Coastguard Worker
run__anonfb3b86bc0111::IterateBeginEnd211*58b9f456SAndroid Build Coastguard Worker void run(benchmark::State& State) const {
212*58b9f456SAndroid Build Coastguard Worker auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
213*58b9f456SAndroid Build Coastguard Worker AccessPattern::Ordered);
214*58b9f456SAndroid Build Coastguard Worker
215*58b9f456SAndroid Build Coastguard Worker while (State.KeepRunningBatch(TableSize * NumTables)) {
216*58b9f456SAndroid Build Coastguard Worker for (auto& Set : Data.Sets) {
217*58b9f456SAndroid Build Coastguard Worker for (auto it = Set.begin(); it != Set.end(); ++it) {
218*58b9f456SAndroid Build Coastguard Worker benchmark::DoNotOptimize(*it);
219*58b9f456SAndroid Build Coastguard Worker }
220*58b9f456SAndroid Build Coastguard Worker }
221*58b9f456SAndroid Build Coastguard Worker }
222*58b9f456SAndroid Build Coastguard Worker }
223*58b9f456SAndroid Build Coastguard Worker
name__anonfb3b86bc0111::IterateBeginEnd224*58b9f456SAndroid Build Coastguard Worker std::string name() const { return "BM_IterateBeginEnd" + baseName(); }
225*58b9f456SAndroid Build Coastguard Worker };
226*58b9f456SAndroid Build Coastguard Worker
227*58b9f456SAndroid Build Coastguard Worker } // namespace
228*58b9f456SAndroid Build Coastguard Worker
main(int argc,char ** argv)229*58b9f456SAndroid Build Coastguard Worker int main(int argc, char** argv) {
230*58b9f456SAndroid Build Coastguard Worker benchmark::Initialize(&argc, argv);
231*58b9f456SAndroid Build Coastguard Worker if (benchmark::ReportUnrecognizedArguments(argc, argv))
232*58b9f456SAndroid Build Coastguard Worker return 1;
233*58b9f456SAndroid Build Coastguard Worker
234*58b9f456SAndroid Build Coastguard Worker const std::vector<size_t> TableSize{1, 10, 100, 1000, 10000, 100000, 1000000};
235*58b9f456SAndroid Build Coastguard Worker const std::vector<size_t> NumTables{1, 10, 100, 1000, 10000, 100000, 1000000};
236*58b9f456SAndroid Build Coastguard Worker
237*58b9f456SAndroid Build Coastguard Worker makeCartesianProductBenchmark<Create, AllAccessPattern>(TableSize, NumTables);
238*58b9f456SAndroid Build Coastguard Worker makeCartesianProductBenchmark<Find, AllHitTypes, AllAccessPattern>(
239*58b9f456SAndroid Build Coastguard Worker TableSize, NumTables);
240*58b9f456SAndroid Build Coastguard Worker makeCartesianProductBenchmark<FindNeEnd, AllHitTypes, AllAccessPattern>(
241*58b9f456SAndroid Build Coastguard Worker TableSize, NumTables);
242*58b9f456SAndroid Build Coastguard Worker makeCartesianProductBenchmark<InsertHit, AllAccessPattern>(
243*58b9f456SAndroid Build Coastguard Worker TableSize, NumTables);
244*58b9f456SAndroid Build Coastguard Worker makeCartesianProductBenchmark<InsertMissAndErase, AllAccessPattern>(
245*58b9f456SAndroid Build Coastguard Worker TableSize, NumTables);
246*58b9f456SAndroid Build Coastguard Worker makeCartesianProductBenchmark<IterateRangeFor>(TableSize, NumTables);
247*58b9f456SAndroid Build Coastguard Worker makeCartesianProductBenchmark<IterateBeginEnd>(TableSize, NumTables);
248*58b9f456SAndroid Build Coastguard Worker benchmark::RunSpecifiedBenchmarks();
249*58b9f456SAndroid Build Coastguard Worker }
250