Skip to content

Instantly share code, notes, and snippets.

@nthery
Last active December 5, 2022 13:18
Show Gist options
  • Save nthery/5876bc9d1559775c4b2df834a78f65b9 to your computer and use it in GitHub Desktop.
Save nthery/5876bc9d1559775c4b2df834a78f65b9 to your computer and use it in GitHub Desktop.
Benchmark map-filter implemented with STL and ranges
#include <vector>
#include <functional>
#include <range/v3/all.hpp>
namespace rv= ranges::view;
inline bool is_odd(int n) {
return n & 1;
}
std::vector<int> map_filter_stl(const std::vector<int>& in) {
std::vector<int> out;
std::transform(in.begin(), in.end(),
std::back_inserter(out),
[](int n) { return n * 3; });
out.erase(std::remove_if(out.begin(), out.end(),
std::not_fn(is_odd)),
out.end());
return out;
}
std::vector<int> map_filter_range(const std::vector<int>& in) {
const auto map_filter =
rv::transform([](int n) {
return n * 3;
}) |
// Not supported by quick-bench version :-( rv::cache1 |
rv::filter([](int n) {
return is_odd(n);
});
std::vector<int> out;
ranges::copy(in | map_filter, ranges::back_inserter(out));
return out;
}
std::vector<int> range_copy_if(const std::vector<int>& in) {
std::vector<int> out;
const auto map = rv::transform([](int n) {
return n * 3;
});
ranges::copy_if(in | map, ranges::back_inserter(out), is_odd);
return out;
}
std::vector<int> map_filter_hand_coded(const std::vector<int>& in) {
std::vector<int> out;
for (int n: in) {
const int x = n * 3;
if (is_odd(x)) {
out.push_back(x);
}
}
return out;
}
std::vector<int> make_vector() {
std::vector<int> v;
ranges::copy(rv::iota(0, 10000), ranges::back_inserter(v));
return v;
}
static void STL(benchmark::State& state) {
const auto v = make_vector();
for (auto _ : state) {
const auto out = map_filter_stl(v);
benchmark::DoNotOptimize(out);
}
}
BENCHMARK(STL);
static void RangesMapFilter(benchmark::State& state) {
const auto v = make_vector();
for (auto _ : state) {
const auto out = map_filter_range(v);
benchmark::DoNotOptimize(out);
}
}
BENCHMARK(RangesMapFilter);
static void RangesCopyIf(benchmark::State& state) {
const auto v = make_vector();
for (auto _ : state) {
const auto out = range_copy_if(v);
benchmark::DoNotOptimize(out);
}
}
BENCHMARK(RangesCopyIf);
static void HandCoded(benchmark::State& state) {
const auto v = make_vector();
for (auto _ : state) {
const auto out = map_filter_hand_coded(v);
benchmark::DoNotOptimize(out);
}
}
BENCHMARK(HandCoded);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment