137632992SSamuel Benzaquen //===----------------------------------------------------------------------===//
237632992SSamuel Benzaquen //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
637632992SSamuel Benzaquen //
737632992SSamuel Benzaquen //===----------------------------------------------------------------------===//
837632992SSamuel Benzaquen
937632992SSamuel Benzaquen #include <algorithm>
1037632992SSamuel Benzaquen #include <cstdint>
1137632992SSamuel Benzaquen #include <memory>
1237632992SSamuel Benzaquen #include <random>
1337632992SSamuel Benzaquen #include <set>
1437632992SSamuel Benzaquen #include <string>
1537632992SSamuel Benzaquen #include <vector>
1637632992SSamuel Benzaquen
17*f938755aSNico Weber #include "CartesianBenchmarks.h"
1837632992SSamuel Benzaquen #include "benchmark/benchmark.h"
1937632992SSamuel Benzaquen #include "test_macros.h"
2037632992SSamuel Benzaquen
2137632992SSamuel Benzaquen namespace {
2237632992SSamuel Benzaquen
2337632992SSamuel Benzaquen enum class HitType { Hit, Miss };
2437632992SSamuel Benzaquen
2537632992SSamuel Benzaquen struct AllHitTypes : EnumValuesAsTuple<AllHitTypes, HitType, 2> {
2637632992SSamuel Benzaquen static constexpr const char* Names[] = {"Hit", "Miss"};
2737632992SSamuel Benzaquen };
2837632992SSamuel Benzaquen
2937632992SSamuel Benzaquen enum class AccessPattern { Ordered, Random };
3037632992SSamuel Benzaquen
3137632992SSamuel Benzaquen struct AllAccessPattern
3237632992SSamuel Benzaquen : EnumValuesAsTuple<AllAccessPattern, AccessPattern, 2> {
3337632992SSamuel Benzaquen static constexpr const char* Names[] = {"Ordered", "Random"};
3437632992SSamuel Benzaquen };
3537632992SSamuel Benzaquen
sortKeysBy(std::vector<uint64_t> & Keys,AccessPattern AP)3637632992SSamuel Benzaquen void sortKeysBy(std::vector<uint64_t>& Keys, AccessPattern AP) {
3737632992SSamuel Benzaquen if (AP == AccessPattern::Random) {
3837632992SSamuel Benzaquen std::random_device R;
3937632992SSamuel Benzaquen std::mt19937 M(R());
4037632992SSamuel Benzaquen std::shuffle(std::begin(Keys), std::end(Keys), M);
4137632992SSamuel Benzaquen }
4237632992SSamuel Benzaquen }
4337632992SSamuel Benzaquen
4437632992SSamuel Benzaquen struct TestSets {
4537632992SSamuel Benzaquen std::vector<std::set<uint64_t> > Sets;
4637632992SSamuel Benzaquen std::vector<uint64_t> Keys;
4737632992SSamuel Benzaquen };
4837632992SSamuel Benzaquen
makeTestingSets(size_t TableSize,size_t NumTables,HitType Hit,AccessPattern Access)4937632992SSamuel Benzaquen TestSets makeTestingSets(size_t TableSize, size_t NumTables, HitType Hit,
5037632992SSamuel Benzaquen AccessPattern Access) {
5137632992SSamuel Benzaquen TestSets R;
5237632992SSamuel Benzaquen R.Sets.resize(1);
5337632992SSamuel Benzaquen
5437632992SSamuel Benzaquen for (uint64_t I = 0; I < TableSize; ++I) {
5537632992SSamuel Benzaquen R.Sets[0].insert(2 * I);
5637632992SSamuel Benzaquen R.Keys.push_back(Hit == HitType::Hit ? 2 * I : 2 * I + 1);
5737632992SSamuel Benzaquen }
5837632992SSamuel Benzaquen R.Sets.resize(NumTables, R.Sets[0]);
5937632992SSamuel Benzaquen sortKeysBy(R.Keys, Access);
6037632992SSamuel Benzaquen
6137632992SSamuel Benzaquen return R;
6237632992SSamuel Benzaquen }
6337632992SSamuel Benzaquen
6437632992SSamuel Benzaquen struct Base {
6537632992SSamuel Benzaquen size_t TableSize;
6637632992SSamuel Benzaquen size_t NumTables;
Base__anon1b7ac9540111::Base6737632992SSamuel Benzaquen Base(size_t T, size_t N) : TableSize(T), NumTables(N) {}
6837632992SSamuel Benzaquen
skip__anon1b7ac9540111::Base6937632992SSamuel Benzaquen bool skip() const {
7037632992SSamuel Benzaquen size_t Total = TableSize * NumTables;
7137632992SSamuel Benzaquen return Total < 100 || Total > 1000000;
7237632992SSamuel Benzaquen }
7337632992SSamuel Benzaquen
baseName__anon1b7ac9540111::Base7437632992SSamuel Benzaquen std::string baseName() const {
7537632992SSamuel Benzaquen return "_TableSize" + std::to_string(TableSize) + "_NumTables" +
7637632992SSamuel Benzaquen std::to_string(NumTables);
7737632992SSamuel Benzaquen }
7837632992SSamuel Benzaquen };
7937632992SSamuel Benzaquen
8037632992SSamuel Benzaquen template <class Access>
8137632992SSamuel Benzaquen struct Create : Base {
8237632992SSamuel Benzaquen using Base::Base;
8337632992SSamuel Benzaquen
run__anon1b7ac9540111::Create8437632992SSamuel Benzaquen void run(benchmark::State& State) const {
852f628a10SSamuel Benzaquen std::vector<uint64_t> Keys(TableSize);
862f628a10SSamuel Benzaquen std::iota(Keys.begin(), Keys.end(), uint64_t{0});
8737632992SSamuel Benzaquen sortKeysBy(Keys, Access());
8837632992SSamuel Benzaquen
8937632992SSamuel Benzaquen while (State.KeepRunningBatch(TableSize * NumTables)) {
902f628a10SSamuel Benzaquen std::vector<std::set<uint64_t>> Sets(NumTables);
9137632992SSamuel Benzaquen for (auto K : Keys) {
9237632992SSamuel Benzaquen for (auto& Set : Sets) {
9337632992SSamuel Benzaquen benchmark::DoNotOptimize(Set.insert(K));
9437632992SSamuel Benzaquen }
9537632992SSamuel Benzaquen }
9637632992SSamuel Benzaquen }
9737632992SSamuel Benzaquen }
9837632992SSamuel Benzaquen
name__anon1b7ac9540111::Create9937632992SSamuel Benzaquen std::string name() const {
10037632992SSamuel Benzaquen return "BM_Create" + Access::name() + baseName();
10137632992SSamuel Benzaquen }
10237632992SSamuel Benzaquen };
10337632992SSamuel Benzaquen
10437632992SSamuel Benzaquen template <class Hit, class Access>
10537632992SSamuel Benzaquen struct Find : Base {
10637632992SSamuel Benzaquen using Base::Base;
10737632992SSamuel Benzaquen
run__anon1b7ac9540111::Find10837632992SSamuel Benzaquen void run(benchmark::State& State) const {
10937632992SSamuel Benzaquen auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
11037632992SSamuel Benzaquen
11137632992SSamuel Benzaquen while (State.KeepRunningBatch(TableSize * NumTables)) {
11237632992SSamuel Benzaquen for (auto K : Data.Keys) {
11337632992SSamuel Benzaquen for (auto& Set : Data.Sets) {
11437632992SSamuel Benzaquen benchmark::DoNotOptimize(Set.find(K));
11537632992SSamuel Benzaquen }
11637632992SSamuel Benzaquen }
11737632992SSamuel Benzaquen }
11837632992SSamuel Benzaquen }
11937632992SSamuel Benzaquen
name__anon1b7ac9540111::Find12037632992SSamuel Benzaquen std::string name() const {
12137632992SSamuel Benzaquen return "BM_Find" + Hit::name() + Access::name() + baseName();
12237632992SSamuel Benzaquen }
12337632992SSamuel Benzaquen };
12437632992SSamuel Benzaquen
12537632992SSamuel Benzaquen template <class Hit, class Access>
12637632992SSamuel Benzaquen struct FindNeEnd : Base {
12737632992SSamuel Benzaquen using Base::Base;
12837632992SSamuel Benzaquen
run__anon1b7ac9540111::FindNeEnd12937632992SSamuel Benzaquen void run(benchmark::State& State) const {
13037632992SSamuel Benzaquen auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
13137632992SSamuel Benzaquen
13237632992SSamuel Benzaquen while (State.KeepRunningBatch(TableSize * NumTables)) {
13337632992SSamuel Benzaquen for (auto K : Data.Keys) {
13437632992SSamuel Benzaquen for (auto& Set : Data.Sets) {
13537632992SSamuel Benzaquen benchmark::DoNotOptimize(Set.find(K) != Set.end());
13637632992SSamuel Benzaquen }
13737632992SSamuel Benzaquen }
13837632992SSamuel Benzaquen }
13937632992SSamuel Benzaquen }
14037632992SSamuel Benzaquen
name__anon1b7ac9540111::FindNeEnd14137632992SSamuel Benzaquen std::string name() const {
14237632992SSamuel Benzaquen return "BM_FindNeEnd" + Hit::name() + Access::name() + baseName();
14337632992SSamuel Benzaquen }
14437632992SSamuel Benzaquen };
14537632992SSamuel Benzaquen
14637632992SSamuel Benzaquen template <class Access>
14737632992SSamuel Benzaquen struct InsertHit : Base {
14837632992SSamuel Benzaquen using Base::Base;
14937632992SSamuel Benzaquen
run__anon1b7ac9540111::InsertHit15037632992SSamuel Benzaquen void run(benchmark::State& State) const {
15137632992SSamuel Benzaquen auto Data = makeTestingSets(TableSize, NumTables, HitType::Hit, Access());
15237632992SSamuel Benzaquen
15337632992SSamuel Benzaquen while (State.KeepRunningBatch(TableSize * NumTables)) {
15437632992SSamuel Benzaquen for (auto K : Data.Keys) {
15537632992SSamuel Benzaquen for (auto& Set : Data.Sets) {
15637632992SSamuel Benzaquen benchmark::DoNotOptimize(Set.insert(K));
15737632992SSamuel Benzaquen }
15837632992SSamuel Benzaquen }
15937632992SSamuel Benzaquen }
16037632992SSamuel Benzaquen }
16137632992SSamuel Benzaquen
name__anon1b7ac9540111::InsertHit16237632992SSamuel Benzaquen std::string name() const {
16337632992SSamuel Benzaquen return "BM_InsertHit" + Access::name() + baseName();
16437632992SSamuel Benzaquen }
16537632992SSamuel Benzaquen };
16637632992SSamuel Benzaquen
16737632992SSamuel Benzaquen template <class Access>
16837632992SSamuel Benzaquen struct InsertMissAndErase : Base {
16937632992SSamuel Benzaquen using Base::Base;
17037632992SSamuel Benzaquen
run__anon1b7ac9540111::InsertMissAndErase17137632992SSamuel Benzaquen void run(benchmark::State& State) const {
17237632992SSamuel Benzaquen auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss, Access());
17337632992SSamuel Benzaquen
17437632992SSamuel Benzaquen while (State.KeepRunningBatch(TableSize * NumTables)) {
17537632992SSamuel Benzaquen for (auto K : Data.Keys) {
17637632992SSamuel Benzaquen for (auto& Set : Data.Sets) {
17737632992SSamuel Benzaquen benchmark::DoNotOptimize(Set.erase(Set.insert(K).first));
17837632992SSamuel Benzaquen }
17937632992SSamuel Benzaquen }
18037632992SSamuel Benzaquen }
18137632992SSamuel Benzaquen }
18237632992SSamuel Benzaquen
name__anon1b7ac9540111::InsertMissAndErase18337632992SSamuel Benzaquen std::string name() const {
18437632992SSamuel Benzaquen return "BM_InsertMissAndErase" + Access::name() + baseName();
18537632992SSamuel Benzaquen }
18637632992SSamuel Benzaquen };
18737632992SSamuel Benzaquen
18837632992SSamuel Benzaquen struct IterateRangeFor : Base {
18937632992SSamuel Benzaquen using Base::Base;
19037632992SSamuel Benzaquen
run__anon1b7ac9540111::IterateRangeFor19137632992SSamuel Benzaquen void run(benchmark::State& State) const {
19237632992SSamuel Benzaquen auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
19337632992SSamuel Benzaquen AccessPattern::Ordered);
19437632992SSamuel Benzaquen
19537632992SSamuel Benzaquen while (State.KeepRunningBatch(TableSize * NumTables)) {
19637632992SSamuel Benzaquen for (auto& Set : Data.Sets) {
19737632992SSamuel Benzaquen for (auto& V : Set) {
19837632992SSamuel Benzaquen benchmark::DoNotOptimize(V);
19937632992SSamuel Benzaquen }
20037632992SSamuel Benzaquen }
20137632992SSamuel Benzaquen }
20237632992SSamuel Benzaquen }
20337632992SSamuel Benzaquen
name__anon1b7ac9540111::IterateRangeFor20437632992SSamuel Benzaquen std::string name() const { return "BM_IterateRangeFor" + baseName(); }
20537632992SSamuel Benzaquen };
20637632992SSamuel Benzaquen
20737632992SSamuel Benzaquen struct IterateBeginEnd : Base {
20837632992SSamuel Benzaquen using Base::Base;
20937632992SSamuel Benzaquen
run__anon1b7ac9540111::IterateBeginEnd21037632992SSamuel Benzaquen void run(benchmark::State& State) const {
21137632992SSamuel Benzaquen auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
21237632992SSamuel Benzaquen AccessPattern::Ordered);
21337632992SSamuel Benzaquen
21437632992SSamuel Benzaquen while (State.KeepRunningBatch(TableSize * NumTables)) {
21537632992SSamuel Benzaquen for (auto& Set : Data.Sets) {
21637632992SSamuel Benzaquen for (auto it = Set.begin(); it != Set.end(); ++it) {
21737632992SSamuel Benzaquen benchmark::DoNotOptimize(*it);
21837632992SSamuel Benzaquen }
21937632992SSamuel Benzaquen }
22037632992SSamuel Benzaquen }
22137632992SSamuel Benzaquen }
22237632992SSamuel Benzaquen
name__anon1b7ac9540111::IterateBeginEnd22337632992SSamuel Benzaquen std::string name() const { return "BM_IterateBeginEnd" + baseName(); }
22437632992SSamuel Benzaquen };
22537632992SSamuel Benzaquen
22637632992SSamuel Benzaquen } // namespace
22737632992SSamuel Benzaquen
main(int argc,char ** argv)22837632992SSamuel Benzaquen int main(int argc, char** argv) {
22937632992SSamuel Benzaquen benchmark::Initialize(&argc, argv);
23037632992SSamuel Benzaquen if (benchmark::ReportUnrecognizedArguments(argc, argv))
23137632992SSamuel Benzaquen return 1;
23237632992SSamuel Benzaquen
23337632992SSamuel Benzaquen const std::vector<size_t> TableSize{1, 10, 100, 1000, 10000, 100000, 1000000};
23437632992SSamuel Benzaquen const std::vector<size_t> NumTables{1, 10, 100, 1000, 10000, 100000, 1000000};
23537632992SSamuel Benzaquen
23637632992SSamuel Benzaquen makeCartesianProductBenchmark<Create, AllAccessPattern>(TableSize, NumTables);
23737632992SSamuel Benzaquen makeCartesianProductBenchmark<Find, AllHitTypes, AllAccessPattern>(
23837632992SSamuel Benzaquen TableSize, NumTables);
23937632992SSamuel Benzaquen makeCartesianProductBenchmark<FindNeEnd, AllHitTypes, AllAccessPattern>(
24037632992SSamuel Benzaquen TableSize, NumTables);
24137632992SSamuel Benzaquen makeCartesianProductBenchmark<InsertHit, AllAccessPattern>(
24237632992SSamuel Benzaquen TableSize, NumTables);
24337632992SSamuel Benzaquen makeCartesianProductBenchmark<InsertMissAndErase, AllAccessPattern>(
24437632992SSamuel Benzaquen TableSize, NumTables);
24537632992SSamuel Benzaquen makeCartesianProductBenchmark<IterateRangeFor>(TableSize, NumTables);
24637632992SSamuel Benzaquen makeCartesianProductBenchmark<IterateBeginEnd>(TableSize, NumTables);
24737632992SSamuel Benzaquen benchmark::RunSpecifiedBenchmarks();
24837632992SSamuel Benzaquen }
249