libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

ordered_set.bench.cpp (6690B)


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