algorithms.partition_point.bench.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #include <array>
  2. #include <algorithm>
  3. #include <cassert>
  4. #include <cstdint>
  5. #include <tuple>
  6. #include <vector>
  7. #include "benchmark/benchmark.h"
  8. #include "CartesianBenchmarks.h"
  9. #include "GenerateInput.h"
  10. namespace {
  11. template <typename I, typename N>
  12. std::array<I, 10> every_10th_percentile_N(I first, N n) {
  13. N step = n / 10;
  14. std::array<I, 10> res;
  15. for (size_t i = 0; i < 10; ++i) {
  16. res[i] = first;
  17. std::advance(first, step);
  18. }
  19. return res;
  20. }
  21. template <class IntT>
  22. struct TestIntBase {
  23. static std::vector<IntT> generateInput(size_t size) {
  24. std::vector<IntT> Res(size);
  25. std::generate(Res.begin(), Res.end(),
  26. [] { return getRandomInteger<IntT>(); });
  27. return Res;
  28. }
  29. };
  30. struct TestInt32 : TestIntBase<std::int32_t> {
  31. static constexpr const char* Name = "TestInt32";
  32. };
  33. struct TestInt64 : TestIntBase<std::int64_t> {
  34. static constexpr const char* Name = "TestInt64";
  35. };
  36. struct TestUint32 : TestIntBase<std::uint32_t> {
  37. static constexpr const char* Name = "TestUint32";
  38. };
  39. struct TestMediumString {
  40. static constexpr const char* Name = "TestMediumString";
  41. static constexpr size_t StringSize = 32;
  42. static std::vector<std::string> generateInput(size_t size) {
  43. std::vector<std::string> Res(size);
  44. std::generate(Res.begin(), Res.end(), [] { return getRandomString(StringSize); });
  45. return Res;
  46. }
  47. };
  48. using AllTestTypes = std::tuple<TestInt32, TestInt64, TestUint32, TestMediumString>;
  49. struct LowerBoundAlg {
  50. template <class I, class V>
  51. I operator()(I first, I last, const V& value) const {
  52. return std::lower_bound(first, last, value);
  53. }
  54. static constexpr const char* Name = "LowerBoundAlg";
  55. };
  56. struct UpperBoundAlg {
  57. template <class I, class V>
  58. I operator()(I first, I last, const V& value) const {
  59. return std::upper_bound(first, last, value);
  60. }
  61. static constexpr const char* Name = "UpperBoundAlg";
  62. };
  63. struct EqualRangeAlg {
  64. template <class I, class V>
  65. std::pair<I, I> operator()(I first, I last, const V& value) const {
  66. return std::equal_range(first, last, value);
  67. }
  68. static constexpr const char* Name = "EqualRangeAlg";
  69. };
  70. using AllAlgs = std::tuple<LowerBoundAlg, UpperBoundAlg, EqualRangeAlg>;
  71. template <class Alg, class TestType>
  72. struct PartitionPointBench {
  73. size_t Quantity;
  74. std::string name() const {
  75. return std::string("PartitionPointBench_") + Alg::Name + "_" +
  76. TestType::Name + '/' + std::to_string(Quantity);
  77. }
  78. void run(benchmark::State& state) const {
  79. auto Data = TestType::generateInput(Quantity);
  80. std::sort(Data.begin(), Data.end());
  81. auto Every10Percentile = every_10th_percentile_N(Data.begin(), Data.size());
  82. for (auto _ : state) {
  83. for (auto Test : Every10Percentile)
  84. benchmark::DoNotOptimize(Alg{}(Data.begin(), Data.end(), *Test));
  85. }
  86. }
  87. };
  88. } // namespace
  89. int main(int argc, char** argv) {
  90. benchmark::Initialize(&argc, argv);
  91. if (benchmark::ReportUnrecognizedArguments(argc, argv))
  92. return 1;
  93. const std::vector<size_t> Quantities = {1 << 8, 1 << 10, 1 << 20};
  94. makeCartesianProductBenchmark<PartitionPointBench, AllAlgs, AllTestTypes>(
  95. Quantities);
  96. benchmark::RunSpecifiedBenchmarks();
  97. }