//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 #include #include #include #include #include #include #include #include "benchmark/benchmark.h" #include "../../GenerateInput.h" int main(int argc, char** argv) { auto std_unique = [](auto first, auto last) { return std::unique(first, last); }; auto std_unique_pred = [](auto first, auto last) { return std::unique(first, last, [](auto a, auto b) { benchmark::DoNotOptimize(a); benchmark::DoNotOptimize(b); return a == b; }); }; auto ranges_unique_pred = [](auto first, auto last) { return std::ranges::unique(first, last, [](auto a, auto b) { benchmark::DoNotOptimize(a); benchmark::DoNotOptimize(b); return a == b; }); }; // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the // adjacent equal elements. // // We perform this benchmark in a batch because we need to restore the // state of the container after the operation. { auto bm = [](std::string name, auto unique) { benchmark::RegisterBenchmark( name, [unique](auto& st) { std::size_t const size = st.range(0); constexpr std::size_t BatchSize = 10; using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); ValueType y = random_different_from({x}); auto populate = [&](Container& cont) { auto half = cont.size() / 2; std::fill_n(std::fill_n(cont.begin(), half, x), half, y); }; for (std::size_t i = 0; i != BatchSize; ++i) { c[i] = Container(size); populate(c[i]); } while (st.KeepRunningBatch(BatchSize)) { for (std::size_t i = 0; i != BatchSize; ++i) { benchmark::DoNotOptimize(c[i]); auto result = unique(c[i].begin(), c[i].end()); benchmark::DoNotOptimize(result); } st.PauseTiming(); for (std::size_t i = 0; i != BatchSize; ++i) { populate(c[i]); } st.ResumeTiming(); } }) ->Arg(32) ->Arg(52) // non power-of-two ->Arg(1024) ->Arg(8192); }; // {std,ranges}::unique(it, it) bm.operator()>("std::unique(vector) (contiguous)", std_unique); bm.operator()>("std::unique(deque) (contiguous)", std_unique); bm.operator()>("std::unique(list) (contiguous)", std_unique); bm.operator()>("rng::unique(vector) (contiguous)", std::ranges::unique); bm.operator()>("rng::unique(deque) (contiguous)", std::ranges::unique); bm.operator()>("rng::unique(list) (contiguous)", std::ranges::unique); // {std,ranges}::unique(it, it, pred) bm.operator()>("std::unique(vector, pred) (contiguous)", std_unique_pred); bm.operator()>("std::unique(deque, pred) (contiguous)", std_unique_pred); bm.operator()>("std::unique(list, pred) (contiguous)", std_unique_pred); bm.operator()>("rng::unique(vector, pred) (contiguous)", ranges_unique_pred); bm.operator()>("rng::unique(deque, pred) (contiguous)", ranges_unique_pred); bm.operator()>("rng::unique(list, pred) (contiguous)", ranges_unique_pred); } // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique // adjacent equal elements. // // We perform this benchmark in a batch because we need to restore the // state of the container after the operation. { auto bm = [](std::string name, auto unique) { benchmark::RegisterBenchmark( name, [unique](auto& st) { std::size_t const size = st.range(0); constexpr std::size_t BatchSize = 10; using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); ValueType y = random_different_from({x}); auto populate = [&](Container& cont) { assert(cont.size() % 4 == 0); auto out = cont.begin(); for (std::size_t i = 0; i != cont.size(); i += 4) { *out++ = x; *out++ = x; *out++ = y; *out++ = y; } }; for (std::size_t i = 0; i != BatchSize; ++i) { c[i] = Container(size); populate(c[i]); } while (st.KeepRunningBatch(BatchSize)) { for (std::size_t i = 0; i != BatchSize; ++i) { benchmark::DoNotOptimize(c[i]); auto result = unique(c[i].begin(), c[i].end()); benchmark::DoNotOptimize(result); } st.PauseTiming(); for (std::size_t i = 0; i != BatchSize; ++i) { populate(c[i]); } st.ResumeTiming(); } }) ->Arg(32) ->Arg(52) // non power-of-two ->Arg(1024) ->Arg(8192); }; // {std,ranges}::unique(it, it) bm.operator()>("std::unique(vector) (sprinkled)", std_unique); bm.operator()>("std::unique(deque) (sprinkled)", std_unique); bm.operator()>("std::unique(list) (sprinkled)", std_unique); bm.operator()>("rng::unique(vector) (sprinkled)", std::ranges::unique); bm.operator()>("rng::unique(deque) (sprinkled)", std::ranges::unique); bm.operator()>("rng::unique(list) (sprinkled)", std::ranges::unique); // {std,ranges}::unique(it, it, pred) bm.operator()>("std::unique(vector, pred) (sprinkled)", std_unique_pred); bm.operator()>("std::unique(deque, pred) (sprinkled)", std_unique_pred); bm.operator()>("std::unique(list, pred) (sprinkled)", std_unique_pred); bm.operator()>("rng::unique(vector, pred) (sprinkled)", ranges_unique_pred); bm.operator()>("rng::unique(deque, pred) (sprinkled)", ranges_unique_pred); bm.operator()>("rng::unique(list, pred) (sprinkled)", ranges_unique_pred); } benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); benchmark::Shutdown(); return 0; }