145 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11#include <algorithm>12#include <cstddef>13#include <deque>14#include <iterator>15#include <list>16#include <string>17#include <vector>18 19#include "benchmark/benchmark.h"20#include "../../GenerateInput.h"21 22int main(int argc, char** argv) {23 auto std_unique_copy = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); };24 auto std_unique_copy_pred = [](auto first, auto last, auto out) {25 return std::unique_copy(first, last, out, [](auto a, auto b) {26 benchmark::DoNotOptimize(a);27 benchmark::DoNotOptimize(b);28 return a == b;29 });30 };31 auto ranges_unique_copy_pred = [](auto first, auto last, auto out) {32 return std::ranges::unique_copy(first, last, out, [](auto a, auto b) {33 benchmark::DoNotOptimize(a);34 benchmark::DoNotOptimize(b);35 return a == b;36 });37 };38 39 // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the40 // adjacent equal elements.41 {42 auto bm = []<class Container>(std::string name, auto unique_copy) {43 benchmark::RegisterBenchmark(44 name,45 [unique_copy](auto& st) {46 std::size_t const size = st.range(0);47 using ValueType = typename Container::value_type;48 Container c(size);49 ValueType x = Generate<ValueType>::random();50 ValueType y = random_different_from({x});51 auto half = size / 2;52 std::fill_n(std::fill_n(c.begin(), half, x), half, y);53 54 std::vector<ValueType> out(size);55 56 for ([[maybe_unused]] auto _ : st) {57 benchmark::DoNotOptimize(c);58 benchmark::DoNotOptimize(out);59 auto result = unique_copy(c.begin(), c.end(), out.begin());60 benchmark::DoNotOptimize(result);61 }62 })63 ->Arg(32)64 ->Arg(52) // non power-of-two65 ->Arg(1024)66 ->Arg(8192);67 };68 // {std,ranges}::unique_copy(it, it, out)69 bm.operator()<std::vector<int>>("std::unique_copy(vector<int>) (contiguous)", std_unique_copy);70 bm.operator()<std::deque<int>>("std::unique_copy(deque<int>) (contiguous)", std_unique_copy);71 bm.operator()<std::list<int>>("std::unique_copy(list<int>) (contiguous)", std_unique_copy);72 bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>) (contiguous)", std::ranges::unique_copy);73 bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>) (contiguous)", std::ranges::unique_copy);74 bm.operator()<std::list<int>>("rng::unique_copy(list<int>) (contiguous)", std::ranges::unique_copy);75 76 // {std,ranges}::unique_copy(it, it, out, pred)77 bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (contiguous)", std_unique_copy_pred);78 bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (contiguous)", std_unique_copy_pred);79 bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (contiguous)", std_unique_copy_pred);80 bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (contiguous)", ranges_unique_copy_pred);81 bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (contiguous)", ranges_unique_copy_pred);82 bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (contiguous)", ranges_unique_copy_pred);83 }84 85 // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique86 // adjacent equal elements.87 {88 auto bm = []<class Container>(std::string name, auto unique_copy) {89 benchmark::RegisterBenchmark(90 name,91 [unique_copy](auto& st) {92 std::size_t const size = st.range(0);93 using ValueType = typename Container::value_type;94 Container c(size);95 ValueType x = Generate<ValueType>::random();96 ValueType y = random_different_from({x});97 auto populate = [&](Container& cont) {98 assert(cont.size() % 4 == 0);99 auto out = cont.begin();100 for (std::size_t i = 0; i != cont.size(); i += 4) {101 *out++ = x;102 *out++ = x;103 *out++ = y;104 *out++ = y;105 }106 };107 populate(c);108 109 std::vector<ValueType> out(size);110 111 for ([[maybe_unused]] auto _ : st) {112 benchmark::DoNotOptimize(c);113 benchmark::DoNotOptimize(out);114 auto result = unique_copy(c.begin(), c.end(), out.begin());115 benchmark::DoNotOptimize(result);116 }117 })118 ->Arg(32)119 ->Arg(52) // non power-of-two120 ->Arg(1024)121 ->Arg(8192);122 };123 // {std,ranges}::unique_copy(it, it, out)124 bm.operator()<std::vector<int>>("std::unique_copy(vector<int>) (sprinkled)", std_unique_copy);125 bm.operator()<std::deque<int>>("std::unique_copy(deque<int>) (sprinkled)", std_unique_copy);126 bm.operator()<std::list<int>>("std::unique_copy(list<int>) (sprinkled)", std_unique_copy);127 bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>) (sprinkled)", std::ranges::unique_copy);128 bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>) (sprinkled)", std::ranges::unique_copy);129 bm.operator()<std::list<int>>("rng::unique_copy(list<int>) (sprinkled)", std::ranges::unique_copy);130 131 // {std,ranges}::unique_copy(it, it, out, pred)132 bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (sprinkled)", std_unique_copy_pred);133 bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (sprinkled)", std_unique_copy_pred);134 bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (sprinkled)", std_unique_copy_pred);135 bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (sprinkled)", ranges_unique_copy_pred);136 bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (sprinkled)", ranges_unique_copy_pred);137 bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (sprinkled)", ranges_unique_copy_pred);138 }139 140 benchmark::Initialize(&argc, argv);141 benchmark::RunSpecifiedBenchmarks();142 benchmark::Shutdown();143 return 0;144}145