Skip to content

Commit 7d797b8

Browse files
committed
Benchmark when memory allocation fails with stable_sort
1 parent 66d56dd commit 7d797b8

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

libcxx/test/benchmarks/algorithms/sorting/stable_sort.bench.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "benchmark/benchmark.h"
1919
#include "common.h"
20+
#include "count_new.h"
2021

2122
int main(int argc, char** argv) {
2223
auto std_stable_sort = [](auto first, auto last) { return std::stable_sort(first, last); };
@@ -84,6 +85,75 @@ int main(int argc, char** argv) {
8485
BENCH(support::heap_data, "heap");
8586
BENCH(support::shuffled_data, "shuffled");
8687
BENCH(support::single_element_data, "repeated");
88+
#undef BENCH
89+
}
90+
91+
// Benchmark {std,ranges}::stable_sort when memory allocation fails. The algorithm must fall back to
92+
// a different algorithm that has different complexity guarantees.
93+
{
94+
auto bm = []<class Container>(std::string name, auto stable_sort, auto generate_data) {
95+
benchmark::RegisterBenchmark(
96+
name,
97+
[stable_sort, generate_data](auto& st) {
98+
std::size_t const size = st.range(0);
99+
constexpr std::size_t BatchSize = 32;
100+
using ValueType = typename Container::value_type;
101+
std::vector<ValueType> data = generate_data(size);
102+
std::array<Container, BatchSize> c;
103+
std::fill_n(c.begin(), BatchSize, Container(data.begin(), data.end()));
104+
105+
while (st.KeepRunningBatch(BatchSize)) {
106+
for (std::size_t i = 0; i != BatchSize; ++i) {
107+
benchmark::DoNotOptimize(c[i]);
108+
// Disable the ability to allocate memory inside this block
109+
globalMemCounter.throw_after = 0;
110+
111+
stable_sort(c[i].begin(), c[i].end());
112+
benchmark::DoNotOptimize(c[i]);
113+
114+
globalMemCounter.reset();
115+
}
116+
117+
st.PauseTiming();
118+
for (std::size_t i = 0; i != BatchSize; ++i) {
119+
std::copy(data.begin(), data.end(), c[i].begin());
120+
}
121+
st.ResumeTiming();
122+
}
123+
})
124+
->Arg(8)
125+
->Arg(1024)
126+
->Arg(8192);
127+
};
128+
#define BENCH(generate_data, name) \
129+
do { \
130+
auto gen1 = [](auto size) { return generate_data<int>(size); }; \
131+
auto gen2 = [](auto size) { \
132+
auto data = generate_data<int>(size); \
133+
std::vector<support::NonIntegral> real_data(data.begin(), data.end()); \
134+
return real_data; \
135+
}; \
136+
bm.operator()<std::vector<int>>("std::stable_sort(vector<int>) (alloc fails, " #name ")", std_stable_sort, gen1); \
137+
bm.operator()<std::vector<support::NonIntegral>>( \
138+
"std::stable_sort(vector<NonIntegral>) (alloc fails, " #name ")", std_stable_sort, gen2); \
139+
bm.operator()<std::deque<int>>("std::stable_sort(deque<int>) (alloc fails, " #name ")", std_stable_sort, gen1); \
140+
\
141+
bm.operator()<std::vector<int>>( \
142+
"rng::stable_sort(vector<int>) (alloc fails, " #name ")", std::ranges::stable_sort, gen1); \
143+
bm.operator()<std::vector<support::NonIntegral>>( \
144+
"rng::stable_sort(vector<NonIntegral>) (alloc fails, " #name ")", std::ranges::stable_sort, gen2); \
145+
bm.operator()<std::deque<int>>( \
146+
"rng::stable_sort(deque<int>) (alloc fails, " #name ")", std::ranges::stable_sort, gen1); \
147+
} while (false)
148+
149+
BENCH(support::quicksort_adversarial_data, "qsort adversarial");
150+
BENCH(support::ascending_sorted_data, "ascending");
151+
BENCH(support::descending_sorted_data, "descending");
152+
BENCH(support::pipe_organ_data, "pipe-organ");
153+
BENCH(support::heap_data, "heap");
154+
BENCH(support::shuffled_data, "shuffled");
155+
BENCH(support::single_element_data, "repeated");
156+
#undef BENCH
87157
}
88158

89159
benchmark::Initialize(&argc, argv);

0 commit comments

Comments
 (0)