Last active
February 4, 2024 08:40
-
-
Save kris-jusiak/e532ec7d8e7bf3a3fa4cbb6d8db64877 to your computer and use it in GitHub Desktop.
Simple generators benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://godbolt.org/z/b9s5cxPao | |
#include <generator> | |
#include <utility> | |
auto generator_baseline() -> int { | |
static THREAD_LOCAL auto i = 0; | |
return i++; | |
} | |
// c++20 coroutines | |
auto generator_coroutines() noexcept(true) -> std::generator<int> { | |
for (auto i = 0;; ++i) { | |
co_yield i; | |
} | |
} | |
auto generator_goto() -> int { | |
if (static THREAD_LOCAL auto state = 0; std::exchange(state, 1)) { | |
goto resume; | |
} | |
for (static THREAD_LOCAL auto i = 0;; ++i) { | |
return i; | |
resume:; | |
} | |
} | |
// computed-goto - gnu::extension | |
auto generator_computed_goto() { | |
static THREAD_LOCAL auto label = &&init; | |
goto *label; | |
init:; | |
for (static THREAD_LOCAL auto i = 0;; ++i) { | |
label = &&resume; | |
return i; | |
resume:; | |
} | |
}; | |
// duff's device | |
auto generator_switch() -> int { | |
switch (static THREAD_LOCAL auto state = 0; state) { | |
case 0: | |
state = 1; | |
for (static THREAD_LOCAL auto i = 0;; ++i) { | |
return i; | |
case 1:; | |
} | |
} | |
return {}; | |
} | |
auto generator_goto_lambda = [i = 0]() mutable -> int { | |
if (static THREAD_LOCAL auto state = 0; std::exchange(state, 1)) { | |
goto resume; | |
} | |
for (i = 0;; ++i) { | |
return i; | |
resume:; | |
} | |
}; | |
// computed-goto - gnu::extension | |
auto generator_computed_goto_lambda = [i = 0]() mutable -> int { | |
static THREAD_LOCAL auto label = &&init; | |
goto *label; | |
init:; | |
for (i = 0;; ++i) { | |
label = &&resume; | |
return i; | |
resume:; | |
} | |
}; | |
#define ANKERL_NANOBENCH_IMPLEMENT | |
#include <nanobench.h> | |
int main() { | |
static constexpr auto iterations = 1'00'000'000; | |
ankerl::nanobench::Bench().minEpochIterations(iterations).run("generator_baseline", [&] { ankerl::nanobench::doNotOptimizeAway(generator_baseline()); }); | |
auto gen = generator_coroutines(); | |
auto it = gen.begin(); | |
ankerl::nanobench::Bench().minEpochIterations(iterations).run("generator_coroutines", [&] { ankerl::nanobench::doNotOptimizeAway(*it); it++; }); | |
ankerl::nanobench::Bench().minEpochIterations(iterations).run("generator_goto", [&] { ankerl::nanobench::doNotOptimizeAway(generator_goto()); }); | |
ankerl::nanobench::Bench().minEpochIterations(iterations).run("generator_computed_goto", [&] { ankerl::nanobench::doNotOptimizeAway(generator_computed_goto()); }); | |
ankerl::nanobench::Bench().minEpochIterations(iterations).run("generator_switch", [&] { ankerl::nanobench::doNotOptimizeAway(generator_switch()); }); | |
ankerl::nanobench::Bench().minEpochIterations(iterations).run("generator_goto_lambda", [&] { ankerl::nanobench::doNotOptimizeAway(generator_goto_lambda()); }); | |
ankerl::nanobench::Bench().minEpochIterations(iterations).run("generator_computed_goto_lambda", [&] { ankerl::nanobench::doNotOptimizeAway(generator_computed_goto_lambda()); }); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment