Skip to content

Commit d3c1f5b

Browse files
committed
Refactor benchmarks per other PRs
1 parent 4ee13a4 commit d3c1f5b

File tree

5 files changed

+189
-188
lines changed

5 files changed

+189
-188
lines changed

libcxx/test/benchmarks/algorithms/partitions/is_partitioned.bench.cpp

Lines changed: 51 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <algorithm>
1212
#include <cassert>
13+
#include <cstddef>
1314
#include <deque>
1415
#include <iterator>
1516
#include <list>
@@ -26,66 +27,66 @@ auto compute_median(auto first, auto last) {
2627
return *middle;
2728
}
2829

29-
template <class Container, bool Partitioned, class Operation>
30-
void bm(std::string operation_name, Operation is_partitioned) {
31-
auto bench = [is_partitioned](auto& st) {
32-
auto const size = st.range(0);
33-
using ValueType = typename Container::value_type;
34-
Container c;
35-
std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
36-
37-
// Partition the container in two equally-sized halves, ensuring the median
38-
// value appears in the left half. Note that the median value isn't located
39-
// in the middle -- this isn't std::nth_element.
40-
ValueType median = compute_median(c.begin(), c.end());
41-
auto pred = [median](auto const& element) { return element <= median; };
42-
std::partition(c.begin(), c.end(), pred);
43-
assert(std::is_partitioned(c.begin(), c.end(), pred));
44-
45-
if constexpr (!Partitioned) {
46-
// De-partition the container by swapping the element containing the median
47-
// value with the last one.
48-
auto median_it = std::find(c.begin(), c.end(), median);
49-
auto last_it = std::next(c.begin(), c.size() - 1);
50-
std::iter_swap(median_it, last_it);
51-
assert(!std::is_partitioned(c.begin(), c.end(), pred));
52-
}
53-
54-
for ([[maybe_unused]] auto _ : st) {
55-
auto result = is_partitioned(c.begin(), c.end(), pred);
56-
benchmark::DoNotOptimize(result);
57-
benchmark::DoNotOptimize(c);
58-
benchmark::ClobberMemory();
59-
}
60-
};
61-
benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
62-
}
63-
6430
int main(int argc, char** argv) {
65-
auto std_is_partitioned = [](auto first, auto last, auto pred) { return std::is_partitioned(first, last, pred); };
66-
auto ranges_is_partitioned = [](auto first, auto last, auto pred) {
67-
return std::ranges::is_partitioned(first, last, pred);
31+
auto std_is_partitioned = [](auto first, auto last, auto pred) { return std::is_partitioned(first, last, pred); };
32+
33+
auto bm = []<class Container, bool Partitioned>(std::string name, auto is_partitioned) {
34+
benchmark::RegisterBenchmark(
35+
name,
36+
[is_partitioned](auto& st) {
37+
std::size_t const size = st.range(0);
38+
using ValueType = typename Container::value_type;
39+
Container c;
40+
std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
41+
42+
// Partition the container in two equally-sized halves, ensuring the median
43+
// value appears in the left half. Note that the median value isn't located
44+
// in the middle -- this isn't std::nth_element.
45+
ValueType median = compute_median(c.begin(), c.end());
46+
auto pred = [median](auto const& element) { return element <= median; };
47+
std::partition(c.begin(), c.end(), pred);
48+
assert(std::is_partitioned(c.begin(), c.end(), pred));
49+
50+
if constexpr (!Partitioned) {
51+
// De-partition the container by swapping the element containing the median
52+
// value with the last one.
53+
auto median_it = std::find(c.begin(), c.end(), median);
54+
auto last_it = std::next(c.begin(), c.size() - 1);
55+
std::iter_swap(median_it, last_it);
56+
assert(!std::is_partitioned(c.begin(), c.end(), pred));
57+
}
58+
59+
for ([[maybe_unused]] auto _ : st) {
60+
benchmark::DoNotOptimize(c);
61+
auto result = is_partitioned(c.begin(), c.end(), pred);
62+
benchmark::DoNotOptimize(result);
63+
}
64+
})
65+
->Arg(32)
66+
->Arg(1024)
67+
->Arg(8192);
6868
};
6969

7070
// std::is_partitioned
71-
bm<std::vector<int>, true>("std::is_partitioned(vector<int>) (partitioned)", std_is_partitioned);
72-
bm<std::vector<int>, false>("std::is_partitioned(vector<int>) (not partitioned)", std_is_partitioned);
71+
bm.operator()<std::vector<int>, true>("std::is_partitioned(vector<int>) (partitioned)", std_is_partitioned);
72+
bm.operator()<std::vector<int>, false>("std::is_partitioned(vector<int>) (unpartitioned)", std_is_partitioned);
7373

74-
bm<std::deque<int>, true>("std::is_partitioned(deque<int>) (partitioned)", std_is_partitioned);
75-
bm<std::deque<int>, false>("std::is_partitioned(deque<int>) (not partitioned)", std_is_partitioned);
74+
bm.operator()<std::deque<int>, true>("std::is_partitioned(deque<int>) (partitioned)", std_is_partitioned);
75+
bm.operator()<std::deque<int>, false>("std::is_partitioned(deque<int>) (unpartitioned)", std_is_partitioned);
7676

77-
bm<std::list<int>, true>("std::is_partitioned(list<int>) (partitioned)", std_is_partitioned);
78-
bm<std::list<int>, false>("std::is_partitioned(list<int>) (not partitioned)", std_is_partitioned);
77+
bm.operator()<std::list<int>, true>("std::is_partitioned(list<int>) (partitioned)", std_is_partitioned);
78+
bm.operator()<std::list<int>, false>("std::is_partitioned(list<int>) (unpartitioned)", std_is_partitioned);
7979

8080
// ranges::is_partitioned
81-
bm<std::vector<int>, true>("ranges::is_partitioned(vector<int>) (partitioned)", ranges_is_partitioned);
82-
bm<std::vector<int>, false>("ranges::is_partitioned(vector<int>) (not partitioned)", ranges_is_partitioned);
81+
bm.operator()<std::vector<int>, true>("rng::is_partitioned(vector<int>) (partitioned)", std::ranges::is_partitioned);
82+
bm.operator()<std::vector<int>, false>(
83+
"rng::is_partitioned(vector<int>) (unpartitioned)", std::ranges::is_partitioned);
8384

84-
bm<std::deque<int>, true>("ranges::is_partitioned(deque<int>) (partitioned)", ranges_is_partitioned);
85-
bm<std::deque<int>, false>("ranges::is_partitioned(deque<int>) (not partitioned)", ranges_is_partitioned);
85+
bm.operator()<std::deque<int>, true>("rng::is_partitioned(deque<int>) (partitioned)", std::ranges::is_partitioned);
86+
bm.operator()<std::deque<int>, false>("rng::is_partitioned(deque<int>) (unpartitioned)", std::ranges::is_partitioned);
8687

87-
bm<std::list<int>, true>("ranges::is_partitioned(list<int>) (partitioned)", ranges_is_partitioned);
88-
bm<std::list<int>, false>("ranges::is_partitioned(list<int>) (not partitioned)", ranges_is_partitioned);
88+
bm.operator()<std::list<int>, true>("rng::is_partitioned(list<int>) (partitioned)", std::ranges::is_partitioned);
89+
bm.operator()<std::list<int>, false>("rng::is_partitioned(list<int>) (unpartitioned)", std::ranges::is_partitioned);
8990

9091
benchmark::Initialize(&argc, argv);
9192
benchmark::RunSpecifiedBenchmarks();

libcxx/test/benchmarks/algorithms/partitions/partition.bench.cpp

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// UNSUPPORTED: c++03, c++11, c++14, c++17
1010

1111
#include <algorithm>
12+
#include <cstddef>
1213
#include <deque>
1314
#include <iterator>
1415
#include <list>
@@ -25,50 +26,50 @@ auto compute_median(auto first, auto last) {
2526
return *middle;
2627
}
2728

28-
template <class Container, class Operation>
29-
void bm(std::string operation_name, Operation partition) {
30-
auto bench = [partition](auto& st) {
31-
auto const size = st.range(0);
32-
using ValueType = typename Container::value_type;
33-
Container c;
34-
std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
29+
int main(int argc, char** argv) {
30+
auto std_partition = [](auto first, auto last, auto pred) { return std::partition(first, last, pred); };
3531

36-
std::vector<ValueType> yes(size), no(size);
37-
ValueType median = compute_median(c.begin(), c.end());
38-
auto pred1 = [median](auto const& element) { return element < median; };
39-
auto pred2 = [median](auto const& element) { return element > median; };
40-
bool toggle = false;
32+
auto bm = []<class Container>(std::string name, auto partition) {
33+
benchmark::RegisterBenchmark(
34+
name,
35+
[partition](auto& st) {
36+
std::size_t const size = st.range(0);
37+
using ValueType = typename Container::value_type;
38+
Container c;
39+
std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
4140

42-
for ([[maybe_unused]] auto _ : st) {
43-
if (toggle) {
44-
auto result = partition(c.begin(), c.end(), pred1);
45-
benchmark::DoNotOptimize(result);
46-
} else {
47-
auto result = partition(c.begin(), c.end(), pred2);
48-
benchmark::DoNotOptimize(result);
49-
}
50-
toggle = !toggle;
41+
std::vector<ValueType> yes(size), no(size);
42+
ValueType median = compute_median(c.begin(), c.end());
43+
auto pred1 = [median](auto const& element) { return element < median; };
44+
auto pred2 = [median](auto const& element) { return element > median; };
45+
bool toggle = false;
5146

52-
benchmark::DoNotOptimize(c);
53-
benchmark::ClobberMemory();
54-
}
47+
for ([[maybe_unused]] auto _ : st) {
48+
benchmark::DoNotOptimize(c);
49+
if (toggle) {
50+
auto result = partition(c.begin(), c.end(), pred1);
51+
benchmark::DoNotOptimize(result);
52+
} else {
53+
auto result = partition(c.begin(), c.end(), pred2);
54+
benchmark::DoNotOptimize(result);
55+
}
56+
toggle = !toggle;
57+
}
58+
})
59+
->Arg(32)
60+
->Arg(1024)
61+
->Arg(8192);
5562
};
56-
benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
57-
}
58-
59-
int main(int argc, char** argv) {
60-
auto std_partition = [](auto first, auto last, auto pred) { return std::partition(first, last, pred); };
61-
auto ranges_partition = [](auto first, auto last, auto pred) { return std::ranges::partition(first, last, pred); };
6263

6364
// std::partition
64-
bm<std::vector<int>>("std::partition(vector<int>)", std_partition);
65-
bm<std::deque<int>>("std::partition(deque<int>)", std_partition);
66-
bm<std::list<int>>("std::partition(list<int>)", std_partition);
65+
bm.operator()<std::vector<int>>("std::partition(vector<int>)", std_partition);
66+
bm.operator()<std::deque<int>>("std::partition(deque<int>)", std_partition);
67+
bm.operator()<std::list<int>>("std::partition(list<int>)", std_partition);
6768

6869
// ranges::partition
69-
bm<std::vector<int>>("ranges::partition(vector<int>)", ranges_partition);
70-
bm<std::deque<int>>("ranges::partition(deque<int>)", ranges_partition);
71-
bm<std::list<int>>("ranges::partition(list<int>)", ranges_partition);
70+
bm.operator()<std::vector<int>>("rng::partition(vector<int>)", std::ranges::partition);
71+
bm.operator()<std::deque<int>>("rng::partition(deque<int>)", std::ranges::partition);
72+
bm.operator()<std::list<int>>("rng::partition(list<int>)", std::ranges::partition);
7273

7374
benchmark::Initialize(&argc, argv);
7475
benchmark::RunSpecifiedBenchmarks();

libcxx/test/benchmarks/algorithms/partitions/partition_copy.bench.cpp

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// UNSUPPORTED: c++03, c++11, c++14, c++17
1010

1111
#include <algorithm>
12+
#include <cstddef>
1213
#include <deque>
1314
#include <iterator>
1415
#include <list>
@@ -25,47 +26,46 @@ auto compute_median(auto first, auto last) {
2526
return *middle;
2627
}
2728

28-
template <class Container, class Operation>
29-
void bm(std::string operation_name, Operation partition_copy) {
30-
auto bench = [partition_copy](auto& st) {
31-
auto const size = st.range(0);
32-
using ValueType = typename Container::value_type;
33-
Container c;
34-
std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
35-
36-
std::vector<ValueType> yes(size), no(size);
37-
ValueType median = compute_median(c.begin(), c.end());
38-
auto pred = [median](auto const& element) { return element < median; };
39-
40-
for ([[maybe_unused]] auto _ : st) {
41-
auto result = partition_copy(c.begin(), c.end(), yes.begin(), no.begin(), pred);
42-
benchmark::DoNotOptimize(yes);
43-
benchmark::DoNotOptimize(no);
44-
benchmark::DoNotOptimize(result);
45-
benchmark::DoNotOptimize(c);
46-
benchmark::ClobberMemory();
47-
}
48-
};
49-
benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
50-
}
51-
5229
int main(int argc, char** argv) {
5330
auto std_partition_copy = [](auto first, auto last, auto out_yes, auto out_no, auto pred) {
5431
return std::partition_copy(first, last, out_yes, out_no, pred);
5532
};
56-
auto ranges_partition_copy = [](auto first, auto last, auto out_yes, auto out_no, auto pred) {
57-
return std::ranges::partition_copy(first, last, out_yes, out_no, pred);
33+
34+
auto bm = []<class Container>(std::string name, auto partition_copy) {
35+
benchmark::RegisterBenchmark(
36+
name,
37+
[partition_copy](auto& st) {
38+
std::size_t const size = st.range(0);
39+
using ValueType = typename Container::value_type;
40+
Container c;
41+
std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
42+
43+
std::vector<ValueType> yes(size), no(size);
44+
ValueType median = compute_median(c.begin(), c.end());
45+
auto pred = [median](auto const& element) { return element < median; };
46+
47+
for ([[maybe_unused]] auto _ : st) {
48+
benchmark::DoNotOptimize(c);
49+
benchmark::DoNotOptimize(yes);
50+
benchmark::DoNotOptimize(no);
51+
auto result = partition_copy(c.begin(), c.end(), yes.begin(), no.begin(), pred);
52+
benchmark::DoNotOptimize(result);
53+
}
54+
})
55+
->Arg(32)
56+
->Arg(1024)
57+
->Arg(8192);
5858
};
5959

6060
// std::partition_copy
61-
bm<std::vector<int>>("std::partition_copy(vector<int>)", std_partition_copy);
62-
bm<std::deque<int>>("std::partition_copy(deque<int>)", std_partition_copy);
63-
bm<std::list<int>>("std::partition_copy(list<int>)", std_partition_copy);
61+
bm.operator()<std::vector<int>>("std::partition_copy(vector<int>)", std_partition_copy);
62+
bm.operator()<std::deque<int>>("std::partition_copy(deque<int>)", std_partition_copy);
63+
bm.operator()<std::list<int>>("std::partition_copy(list<int>)", std_partition_copy);
6464

6565
// ranges::partition_copy
66-
bm<std::vector<int>>("ranges::partition_copy(vector<int>)", ranges_partition_copy);
67-
bm<std::deque<int>>("ranges::partition_copy(deque<int>)", ranges_partition_copy);
68-
bm<std::list<int>>("ranges::partition_copy(list<int>)", ranges_partition_copy);
66+
bm.operator()<std::vector<int>>("rng::partition_copy(vector<int>)", std::ranges::partition_copy);
67+
bm.operator()<std::deque<int>>("rng::partition_copy(deque<int>)", std::ranges::partition_copy);
68+
bm.operator()<std::list<int>>("rng::partition_copy(list<int>)", std::ranges::partition_copy);
6969

7070
benchmark::Initialize(&argc, argv);
7171
benchmark::RunSpecifiedBenchmarks();

libcxx/test/benchmarks/algorithms/partitions/partition_point.bench.cpp

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// UNSUPPORTED: c++03, c++11, c++14, c++17
1010

1111
#include <algorithm>
12+
#include <cstddef>
1213
#include <deque>
1314
#include <iterator>
1415
#include <list>
@@ -25,46 +26,45 @@ auto compute_median(auto first, auto last) {
2526
return *middle;
2627
}
2728

28-
template <class Container, class Operation>
29-
void bm(std::string operation_name, Operation partition_point) {
30-
auto bench = [partition_point](auto& st) {
31-
auto const size = st.range(0);
32-
using ValueType = typename Container::value_type;
33-
Container c;
34-
std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
29+
int main(int argc, char** argv) {
30+
auto std_partition_point = [](auto first, auto last, auto pred) { return std::partition_point(first, last, pred); };
3531

36-
// Partition the container in two equally-sized halves. Based on experimentation, the running
37-
// time of the algorithm doesn't change much depending on the size of the halves.
38-
ValueType median = compute_median(c.begin(), c.end());
39-
auto pred = [median](auto const& element) { return element < median; };
40-
std::partition(c.begin(), c.end(), pred);
41-
assert(std::is_partitioned(c.begin(), c.end(), pred));
32+
auto bm = []<class Container>(std::string name, auto partition_point) {
33+
benchmark::RegisterBenchmark(
34+
name,
35+
[partition_point](auto& st) {
36+
std::size_t const size = st.range(0);
37+
using ValueType = typename Container::value_type;
38+
Container c;
39+
std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
4240

43-
for ([[maybe_unused]] auto _ : st) {
44-
auto result = partition_point(c.begin(), c.end(), pred);
45-
benchmark::DoNotOptimize(result);
46-
benchmark::DoNotOptimize(c);
47-
benchmark::ClobberMemory();
48-
}
49-
};
50-
benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
51-
}
41+
// Partition the container in two equally-sized halves. Based on experimentation, the running
42+
// time of the algorithm doesn't change much depending on the size of the halves.
43+
ValueType median = compute_median(c.begin(), c.end());
44+
auto pred = [median](auto const& element) { return element < median; };
45+
std::partition(c.begin(), c.end(), pred);
46+
assert(std::is_partitioned(c.begin(), c.end(), pred));
5247

53-
int main(int argc, char** argv) {
54-
auto std_partition_point = [](auto first, auto last, auto pred) { return std::partition_point(first, last, pred); };
55-
auto ranges_partition_point = [](auto first, auto last, auto pred) {
56-
return std::ranges::partition_point(first, last, pred);
48+
for ([[maybe_unused]] auto _ : st) {
49+
benchmark::DoNotOptimize(c);
50+
auto result = partition_point(c.begin(), c.end(), pred);
51+
benchmark::DoNotOptimize(result);
52+
}
53+
})
54+
->Arg(32)
55+
->Arg(1024)
56+
->Arg(8192);
5757
};
5858

5959
// std::partition_point
60-
bm<std::vector<int>>("std::partition_point(vector<int>)", std_partition_point);
61-
bm<std::deque<int>>("std::partition_point(deque<int>)", std_partition_point);
62-
bm<std::list<int>>("std::partition_point(list<int>)", std_partition_point);
60+
bm.operator()<std::vector<int>>("std::partition_point(vector<int>)", std_partition_point);
61+
bm.operator()<std::deque<int>>("std::partition_point(deque<int>)", std_partition_point);
62+
bm.operator()<std::list<int>>("std::partition_point(list<int>)", std_partition_point);
6363

6464
// ranges::partition_point
65-
bm<std::vector<int>>("ranges::partition_point(vector<int>)", ranges_partition_point);
66-
bm<std::deque<int>>("ranges::partition_point(deque<int>)", ranges_partition_point);
67-
bm<std::list<int>>("ranges::partition_point(list<int>)", ranges_partition_point);
65+
bm.operator()<std::vector<int>>("rng::partition_point(vector<int>)", std::ranges::partition_point);
66+
bm.operator()<std::deque<int>>("rng::partition_point(deque<int>)", std::ranges::partition_point);
67+
bm.operator()<std::list<int>>("rng::partition_point(list<int>)", std::ranges::partition_point);
6868

6969
benchmark::Initialize(&argc, argv);
7070
benchmark::RunSpecifiedBenchmarks();

0 commit comments

Comments
 (0)