Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: Benchmarks for construct, find, insert and iterate, with sequential and random ordered inputs. It also improves the cartesian product benchmark header to allow for runtime values to be specified in the product. Reviewers: EricWF Subscribers: christof, ldionne, libcxx-commits Differential Revision: https://reviews.llvm.org/D53523 llvm-svn: 345035
- Loading branch information
1 parent
ad76c68
commit 3763299
Showing
2 changed files
with
312 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is dual licensed under the MIT and the University of Illinois Open | ||
// Source Licenses. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include <algorithm> | ||
#include <cstdint> | ||
#include <memory> | ||
#include <random> | ||
#include <set> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "CartesianBenchmarks.hpp" | ||
#include "benchmark/benchmark.h" | ||
#include "test_macros.h" | ||
|
||
namespace { | ||
|
||
enum class HitType { Hit, Miss }; | ||
|
||
struct AllHitTypes : EnumValuesAsTuple<AllHitTypes, HitType, 2> { | ||
static constexpr const char* Names[] = {"Hit", "Miss"}; | ||
}; | ||
|
||
enum class AccessPattern { Ordered, Random }; | ||
|
||
struct AllAccessPattern | ||
: EnumValuesAsTuple<AllAccessPattern, AccessPattern, 2> { | ||
static constexpr const char* Names[] = {"Ordered", "Random"}; | ||
}; | ||
|
||
void sortKeysBy(std::vector<uint64_t>& Keys, AccessPattern AP) { | ||
if (AP == AccessPattern::Random) { | ||
std::random_device R; | ||
std::mt19937 M(R()); | ||
std::shuffle(std::begin(Keys), std::end(Keys), M); | ||
} | ||
} | ||
|
||
struct TestSets { | ||
std::vector<std::set<uint64_t> > Sets; | ||
std::vector<uint64_t> Keys; | ||
}; | ||
|
||
TestSets makeTestingSets(size_t TableSize, size_t NumTables, HitType Hit, | ||
AccessPattern Access) { | ||
TestSets R; | ||
R.Sets.resize(1); | ||
|
||
for (uint64_t I = 0; I < TableSize; ++I) { | ||
R.Sets[0].insert(2 * I); | ||
R.Keys.push_back(Hit == HitType::Hit ? 2 * I : 2 * I + 1); | ||
} | ||
R.Sets.resize(NumTables, R.Sets[0]); | ||
sortKeysBy(R.Keys, Access); | ||
|
||
return R; | ||
} | ||
|
||
struct Base { | ||
size_t TableSize; | ||
size_t NumTables; | ||
Base(size_t T, size_t N) : TableSize(T), NumTables(N) {} | ||
|
||
bool skip() const { | ||
size_t Total = TableSize * NumTables; | ||
return Total < 100 || Total > 1000000; | ||
} | ||
|
||
std::string baseName() const { | ||
return "_TableSize" + std::to_string(TableSize) + "_NumTables" + | ||
std::to_string(NumTables); | ||
} | ||
}; | ||
|
||
template <class Access> | ||
struct Create : Base { | ||
using Base::Base; | ||
|
||
void run(benchmark::State& State) const { | ||
std::vector<size_t> Keys(TableSize); | ||
std::iota(Keys.begin(), Keys.end(), size_t{0}); | ||
sortKeysBy(Keys, Access()); | ||
|
||
while (State.KeepRunningBatch(TableSize * NumTables)) { | ||
std::vector<std::set<size_t>> Sets(NumTables); | ||
for (auto K : Keys) { | ||
for (auto& Set : Sets) { | ||
benchmark::DoNotOptimize(Set.insert(K)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
std::string name() const { | ||
return "BM_Create" + Access::name() + baseName(); | ||
} | ||
}; | ||
|
||
template <class Hit, class Access> | ||
struct Find : Base { | ||
using Base::Base; | ||
|
||
void run(benchmark::State& State) const { | ||
auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access()); | ||
|
||
while (State.KeepRunningBatch(TableSize * NumTables)) { | ||
for (auto K : Data.Keys) { | ||
for (auto& Set : Data.Sets) { | ||
benchmark::DoNotOptimize(Set.find(K)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
std::string name() const { | ||
return "BM_Find" + Hit::name() + Access::name() + baseName(); | ||
} | ||
}; | ||
|
||
template <class Hit, class Access> | ||
struct FindNeEnd : Base { | ||
using Base::Base; | ||
|
||
void run(benchmark::State& State) const { | ||
auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access()); | ||
|
||
while (State.KeepRunningBatch(TableSize * NumTables)) { | ||
for (auto K : Data.Keys) { | ||
for (auto& Set : Data.Sets) { | ||
benchmark::DoNotOptimize(Set.find(K) != Set.end()); | ||
} | ||
} | ||
} | ||
} | ||
|
||
std::string name() const { | ||
return "BM_FindNeEnd" + Hit::name() + Access::name() + baseName(); | ||
} | ||
}; | ||
|
||
template <class Access> | ||
struct InsertHit : Base { | ||
using Base::Base; | ||
|
||
void run(benchmark::State& State) const { | ||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Hit, Access()); | ||
|
||
while (State.KeepRunningBatch(TableSize * NumTables)) { | ||
for (auto K : Data.Keys) { | ||
for (auto& Set : Data.Sets) { | ||
benchmark::DoNotOptimize(Set.insert(K)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
std::string name() const { | ||
return "BM_InsertHit" + Access::name() + baseName(); | ||
} | ||
}; | ||
|
||
template <class Access> | ||
struct InsertMissAndErase : Base { | ||
using Base::Base; | ||
|
||
void run(benchmark::State& State) const { | ||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss, Access()); | ||
|
||
while (State.KeepRunningBatch(TableSize * NumTables)) { | ||
for (auto K : Data.Keys) { | ||
for (auto& Set : Data.Sets) { | ||
benchmark::DoNotOptimize(Set.erase(Set.insert(K).first)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
std::string name() const { | ||
return "BM_InsertMissAndErase" + Access::name() + baseName(); | ||
} | ||
}; | ||
|
||
struct IterateRangeFor : Base { | ||
using Base::Base; | ||
|
||
void run(benchmark::State& State) const { | ||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss, | ||
AccessPattern::Ordered); | ||
|
||
while (State.KeepRunningBatch(TableSize * NumTables)) { | ||
for (auto& Set : Data.Sets) { | ||
for (auto& V : Set) { | ||
benchmark::DoNotOptimize(V); | ||
} | ||
} | ||
} | ||
} | ||
|
||
std::string name() const { return "BM_IterateRangeFor" + baseName(); } | ||
}; | ||
|
||
struct IterateBeginEnd : Base { | ||
using Base::Base; | ||
|
||
void run(benchmark::State& State) const { | ||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss, | ||
AccessPattern::Ordered); | ||
|
||
while (State.KeepRunningBatch(TableSize * NumTables)) { | ||
for (auto& Set : Data.Sets) { | ||
for (auto it = Set.begin(); it != Set.end(); ++it) { | ||
benchmark::DoNotOptimize(*it); | ||
} | ||
} | ||
} | ||
} | ||
|
||
std::string name() const { return "BM_IterateBeginEnd" + baseName(); } | ||
}; | ||
|
||
} // namespace | ||
|
||
int main(int argc, char** argv) { | ||
benchmark::Initialize(&argc, argv); | ||
if (benchmark::ReportUnrecognizedArguments(argc, argv)) | ||
return 1; | ||
|
||
const std::vector<size_t> TableSize{1, 10, 100, 1000, 10000, 100000, 1000000}; | ||
const std::vector<size_t> NumTables{1, 10, 100, 1000, 10000, 100000, 1000000}; | ||
|
||
makeCartesianProductBenchmark<Create, AllAccessPattern>(TableSize, NumTables); | ||
makeCartesianProductBenchmark<Find, AllHitTypes, AllAccessPattern>( | ||
TableSize, NumTables); | ||
makeCartesianProductBenchmark<FindNeEnd, AllHitTypes, AllAccessPattern>( | ||
TableSize, NumTables); | ||
makeCartesianProductBenchmark<InsertHit, AllAccessPattern>( | ||
TableSize, NumTables); | ||
makeCartesianProductBenchmark<InsertMissAndErase, AllAccessPattern>( | ||
TableSize, NumTables); | ||
makeCartesianProductBenchmark<IterateRangeFor>(TableSize, NumTables); | ||
makeCartesianProductBenchmark<IterateBeginEnd>(TableSize, NumTables); | ||
benchmark::RunSpecifiedBenchmarks(); | ||
} |