aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/tests/coro/generator/generator_bench.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vespalib/src/tests/coro/generator/generator_bench.cpp')
-rw-r--r--vespalib/src/tests/coro/generator/generator_bench.cpp144
1 files changed, 76 insertions, 68 deletions
diff --git a/vespalib/src/tests/coro/generator/generator_bench.cpp b/vespalib/src/tests/coro/generator/generator_bench.cpp
index ab0bcdc5c97..ae0e0fce894 100644
--- a/vespalib/src/tests/coro/generator/generator_bench.cpp
+++ b/vespalib/src/tests/coro/generator/generator_bench.cpp
@@ -11,8 +11,23 @@ using vespalib::coro::Generator;
using vespalib::BenchmarkTimer;
using vespalib::Sequence;
-template <std::ranges::input_range T>
-size_t calc_sum(T&& values) {
+size_t calc_sum(const std::vector<size_t> &values) {
+ size_t sum = 0;
+ for (auto&& value: values) {
+ sum += value;
+ }
+ return sum;
+}
+
+size_t calc_sum(Generator<size_t> values) {
+ size_t sum = 0;
+ for (auto&& value: values) {
+ sum += value;
+ }
+ return sum;
+}
+
+size_t calc_sum(Generator<const size_t &> values) {
size_t sum = 0;
for (auto&& value: values) {
sum += value;
@@ -28,91 +43,84 @@ size_t calc_sum(Sequence<size_t> &seq) {
return sum;
}
-struct ValueRange {
- using iterator_concept = std::input_iterator_tag;
- using difference_type = std::ptrdiff_t;
- using value_type = size_t;
- size_t first;
- size_t last;
- ValueRange() noexcept : first(0), last(0) {}
- ValueRange(size_t first_in, size_t last_in) noexcept
- : first(first_in), last(last_in) {}
- auto begin() noexcept { return ValueRange(first, last); }
- auto end() const noexcept { return std::default_sentinel_t(); }
- bool operator==(std::default_sentinel_t) const noexcept { return (first == last); }
- ValueRange &operator++() noexcept { ++first; return *this; }
- void operator++(int) noexcept { operator++(); }
- size_t operator*() const noexcept { return first; }
+std::vector<size_t> make_data() __attribute__((noinline));
+std::vector<size_t> make_data() {
+ size_t n = 1000000;
+ std::vector<size_t> data;
+ data.reserve(n);
+ for (size_t i = 0; i < n; ++i) {
+ data.push_back(i + n);
+ }
+ return data;
+}
+
+struct MySeq : Sequence<size_t> {
+ const std::vector<size_t> &data;
+ size_t pos;
+ MySeq(const std::vector<size_t> &data_in)
+ : data(data_in), pos(0) {}
+ bool valid() const override { return pos < data.size(); }
+ size_t get() const override { return data[pos]; }
+ void next() override { ++pos; }
};
-size_t calc_sum_direct(size_t first, size_t last) {
- return calc_sum(ValueRange(first, last));
+size_t calc_sum_direct(const std::vector<size_t> &data) {
+ return calc_sum(data);
}
-Generator<size_t> gen_values(size_t first, size_t last) {
- for (size_t i = first; i < last; ++i) {
- co_yield i;
+size_t calc_sum_sequence(const std::vector<size_t> &data) {
+ MySeq my_seq(data);
+ return calc_sum(my_seq);
+}
+
+Generator<size_t> gen_values(const std::vector<size_t> &data) {
+ for (size_t value: data) {
+ co_yield value;
}
}
-size_t calc_sum_generator(size_t first, size_t last) {
- return calc_sum(gen_values(first, last));
+size_t calc_sum_generator(const std::vector<size_t> &data) {
+ return calc_sum(gen_values(data));
}
-Generator<const size_t &> gen_values_ref(size_t first, size_t last) {
- for (size_t i = first; i < last; ++i) {
- co_yield i;
+Generator<const size_t &> gen_values_noinline(const std::vector<size_t> &data) __attribute__((noinline));
+Generator<const size_t &> gen_values_noinline(const std::vector<size_t> &data) {
+ for (const size_t &value: data) {
+ co_yield value;
}
}
-size_t calc_sum_generator_ref(size_t first, size_t last) {
- return calc_sum(gen_values_ref(first, last));
+size_t calc_sum_generator_noinline(const std::vector<size_t> &data) {
+ return calc_sum(gen_values_noinline(data));
}
-struct MySeq : Sequence<size_t> {
- size_t first;
- size_t last;
- MySeq(size_t first_in, size_t last_in)
- : first(first_in), last(last_in) {}
- bool valid() const override { return (first < last); }
- size_t get() const override { return first; }
- void next() override { ++first; }
-};
-
-size_t calc_sum_sequence(size_t first, size_t last) {
- MySeq seq(first, last);
- return calc_sum(seq);
+double bench(auto fun, const std::vector<size_t> &data, size_t &res) {
+ BenchmarkTimer timer(5.0);
+ while (timer.has_budget()) {
+ timer.before();
+ res = fun(data);
+ timer.after();
+ }
+ return timer.min_time() * 1000.0;
}
TEST(GeneratorBench, direct_vs_generated_for_loop) {
- size_t first = 0;
- size_t last = 100000;
- size_t res_direct = 0;
- size_t res_generator = 1;
- size_t res_generator_ref = 2;
- size_t res_sequence = 3;
- double direct_ms = BenchmarkTimer::benchmark([first,last,&res_direct](){
- res_direct = calc_sum_direct(first, last);
- }, 5.0) * 1000.0;
- fprintf(stderr, "direct: %g ms\n", direct_ms);
- double generator_ms = BenchmarkTimer::benchmark([first,last,&res_generator](){
- res_generator = calc_sum_generator(first, last);
- }, 5.0) * 1000.0;
- fprintf(stderr, "generator: %g ms\n", generator_ms);
- double generator_ref_ms = BenchmarkTimer::benchmark([first,last,&res_generator_ref](){
- res_generator_ref = calc_sum_generator_ref(first, last);
- }, 5.0) * 1000.0;
- fprintf(stderr, "generator_ref: %g ms\n", generator_ref_ms);
- double sequence_ms = BenchmarkTimer::benchmark([first,last,&res_sequence](){
- res_sequence = calc_sum_sequence(first, last);
- }, 5.0) * 1000.0;
+ auto data = make_data();
+ size_t result[4] = { 0, 1, 2, 3 };
+ double sequence_ms = bench(calc_sum_sequence, data, result[0]);
fprintf(stderr, "sequence: %g ms\n", sequence_ms);
- EXPECT_EQ(res_direct, res_generator);
- EXPECT_EQ(res_direct, res_generator_ref);
- EXPECT_EQ(res_direct, res_sequence);
+ double generator_noinline_ms = bench(calc_sum_generator_noinline, data, result[1]);
+ fprintf(stderr, "generator_noinline: %g ms\n", generator_noinline_ms);
+ double generator_ms = bench(calc_sum_generator, data, result[2]);
+ fprintf(stderr, "generator: %g ms\n", generator_ms);
+ double direct_ms = bench(calc_sum_direct, data, result[3]);
+ fprintf(stderr, "direct: %g ms\n", direct_ms);
+ EXPECT_EQ(result[0], result[1]);
+ EXPECT_EQ(result[0], result[2]);
+ EXPECT_EQ(result[0], result[3]);
fprintf(stderr, "ratio (generator/direct): %g\n", (generator_ms/direct_ms));
- fprintf(stderr, "ratio (generator/sequence): %g\n", (generator_ms/sequence_ms));
- fprintf(stderr, "ratio (generator/generator_ref): %g\n", (generator_ms/generator_ref_ms));
+ fprintf(stderr, "ratio (generator_noinline/generator): %g\n", (generator_noinline_ms/generator_ms));
+ fprintf(stderr, "ratio (sequence/generator): %g\n", (sequence_ms/generator_ms));
}
GTEST_MAIN_RUN_ALL_TESTS()