146035553Spatrick #include <array>
246035553Spatrick #include <algorithm>
346035553Spatrick #include <cassert>
446035553Spatrick #include <cstdint>
546035553Spatrick #include <tuple>
646035553Spatrick #include <vector>
746035553Spatrick
846035553Spatrick #include "benchmark/benchmark.h"
946035553Spatrick
1046035553Spatrick #include "CartesianBenchmarks.h"
1146035553Spatrick #include "GenerateInput.h"
1246035553Spatrick
1346035553Spatrick namespace {
1446035553Spatrick
1546035553Spatrick template <typename I, typename N>
every_10th_percentile_N(I first,N n)1646035553Spatrick std::array<I, 10> every_10th_percentile_N(I first, N n) {
1746035553Spatrick N step = n / 10;
1846035553Spatrick std::array<I, 10> res;
1946035553Spatrick
2046035553Spatrick for (size_t i = 0; i < 10; ++i) {
2146035553Spatrick res[i] = first;
2246035553Spatrick std::advance(first, step);
2346035553Spatrick }
2446035553Spatrick
2546035553Spatrick return res;
2646035553Spatrick }
2746035553Spatrick
2846035553Spatrick template <class IntT>
2946035553Spatrick struct TestIntBase {
generateInput__anone332a8960111::TestIntBase3046035553Spatrick static std::vector<IntT> generateInput(size_t size) {
3146035553Spatrick std::vector<IntT> Res(size);
3246035553Spatrick std::generate(Res.begin(), Res.end(),
33*4bdff4beSrobert [] { return getRandomInteger<IntT>(0, std::numeric_limits<IntT>::max()); });
3446035553Spatrick return Res;
3546035553Spatrick }
3646035553Spatrick };
3746035553Spatrick
3846035553Spatrick struct TestInt32 : TestIntBase<std::int32_t> {
3946035553Spatrick static constexpr const char* Name = "TestInt32";
4046035553Spatrick };
4146035553Spatrick
4246035553Spatrick struct TestInt64 : TestIntBase<std::int64_t> {
4346035553Spatrick static constexpr const char* Name = "TestInt64";
4446035553Spatrick };
4546035553Spatrick
4646035553Spatrick struct TestUint32 : TestIntBase<std::uint32_t> {
4746035553Spatrick static constexpr const char* Name = "TestUint32";
4846035553Spatrick };
4946035553Spatrick
5046035553Spatrick struct TestMediumString {
5146035553Spatrick static constexpr const char* Name = "TestMediumString";
5246035553Spatrick static constexpr size_t StringSize = 32;
5346035553Spatrick
generateInput__anone332a8960111::TestMediumString5446035553Spatrick static std::vector<std::string> generateInput(size_t size) {
5546035553Spatrick std::vector<std::string> Res(size);
5646035553Spatrick std::generate(Res.begin(), Res.end(), [] { return getRandomString(StringSize); });
5746035553Spatrick return Res;
5846035553Spatrick }
5946035553Spatrick };
6046035553Spatrick
6146035553Spatrick using AllTestTypes = std::tuple<TestInt32, TestInt64, TestUint32, TestMediumString>;
6246035553Spatrick
6346035553Spatrick struct LowerBoundAlg {
6446035553Spatrick template <class I, class V>
operator ()__anone332a8960111::LowerBoundAlg6546035553Spatrick I operator()(I first, I last, const V& value) const {
6646035553Spatrick return std::lower_bound(first, last, value);
6746035553Spatrick }
6846035553Spatrick
6946035553Spatrick static constexpr const char* Name = "LowerBoundAlg";
7046035553Spatrick };
7146035553Spatrick
7246035553Spatrick struct UpperBoundAlg {
7346035553Spatrick template <class I, class V>
operator ()__anone332a8960111::UpperBoundAlg7446035553Spatrick I operator()(I first, I last, const V& value) const {
7546035553Spatrick return std::upper_bound(first, last, value);
7646035553Spatrick }
7746035553Spatrick
7846035553Spatrick static constexpr const char* Name = "UpperBoundAlg";
7946035553Spatrick };
8046035553Spatrick
8146035553Spatrick struct EqualRangeAlg {
8246035553Spatrick template <class I, class V>
operator ()__anone332a8960111::EqualRangeAlg8346035553Spatrick std::pair<I, I> operator()(I first, I last, const V& value) const {
8446035553Spatrick return std::equal_range(first, last, value);
8546035553Spatrick }
8646035553Spatrick
8746035553Spatrick static constexpr const char* Name = "EqualRangeAlg";
8846035553Spatrick };
8946035553Spatrick
9046035553Spatrick using AllAlgs = std::tuple<LowerBoundAlg, UpperBoundAlg, EqualRangeAlg>;
9146035553Spatrick
9246035553Spatrick template <class Alg, class TestType>
9346035553Spatrick struct PartitionPointBench {
9446035553Spatrick size_t Quantity;
9546035553Spatrick
name__anone332a8960111::PartitionPointBench9646035553Spatrick std::string name() const {
9746035553Spatrick return std::string("PartitionPointBench_") + Alg::Name + "_" +
9846035553Spatrick TestType::Name + '/' + std::to_string(Quantity);
9946035553Spatrick }
10046035553Spatrick
run__anone332a8960111::PartitionPointBench10146035553Spatrick void run(benchmark::State& state) const {
10246035553Spatrick auto Data = TestType::generateInput(Quantity);
10346035553Spatrick std::sort(Data.begin(), Data.end());
10446035553Spatrick auto Every10Percentile = every_10th_percentile_N(Data.begin(), Data.size());
10546035553Spatrick
10646035553Spatrick for (auto _ : state) {
10746035553Spatrick for (auto Test : Every10Percentile)
10846035553Spatrick benchmark::DoNotOptimize(Alg{}(Data.begin(), Data.end(), *Test));
10946035553Spatrick }
11046035553Spatrick }
11146035553Spatrick };
11246035553Spatrick
11346035553Spatrick } // namespace
11446035553Spatrick
main(int argc,char ** argv)11546035553Spatrick int main(int argc, char** argv) {
11646035553Spatrick benchmark::Initialize(&argc, argv);
11746035553Spatrick if (benchmark::ReportUnrecognizedArguments(argc, argv))
11846035553Spatrick return 1;
11946035553Spatrick
12046035553Spatrick const std::vector<size_t> Quantities = {1 << 8, 1 << 10, 1 << 20};
12146035553Spatrick makeCartesianProductBenchmark<PartitionPointBench, AllAlgs, AllTestTypes>(
12246035553Spatrick Quantities);
12346035553Spatrick benchmark::RunSpecifiedBenchmarks();
12446035553Spatrick }
125