Skip to content

Commit 50eb099

Browse files
committed
Add vector<bool> benchmark and cover more segmented iterators
1 parent 1924d9e commit 50eb099

File tree

8 files changed

+292
-150
lines changed

8 files changed

+292
-150
lines changed

libcxx/include/__algorithm/copy.h

+1-5
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,7 @@ struct __copy_impl {
248248
return std::make_pair(__last, std::__copy_unaligned(__first, __last, __result));
249249
}
250250

251-
template <class _InIter,
252-
class _OutIter,
253-
class _Cp,
254-
bool _IsConst,
255-
__enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
251+
template <class _InIter, class _Cp, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
256252
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, __bit_iterator<_Cp, false> >
257253
operator()(_InIter __first, _InIter __last, __bit_iterator<_Cp, /* IsConst = */ false> __result) const {
258254
std::__for_each_segment(__first, __last, _CopySegment<_InIter, __bit_iterator<_Cp, false> >(__result));

libcxx/include/__bit_reference

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <__functional/identity.h>
2828
#include <__fwd/bit_reference.h>
2929
#include <__iterator/iterator_traits.h>
30+
#include <__iterator/segmented_iterator.h>
3031
#include <__memory/construct_at.h>
3132
#include <__memory/pointer_traits.h>
3233
#include <__type_traits/conditional.h>

libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,15 @@ int main(int argc, char** argv) {
5252
bm.operator()<std::deque<int>>("rng::copy(deque<int>)", std::ranges::copy);
5353
bm.operator()<std::list<int>>("rng::copy(list<int>)", std::ranges::copy);
5454

55+
#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
5556
// Copy from normal containers to vector<bool>
5657
bm.operator()<std::vector<int>, std::vector<bool>>("std::copy(vector<int>, std::vector<bool>)", std_copy);
5758
bm.operator()<std::deque<int>, std::vector<bool>>("std::copy(deque<int>, std::vector<bool>)", std_copy);
5859
bm.operator()<std::list<int>, std::vector<bool>>("std::copy(list<int>, std::vector<bool>)", std_copy);
5960
bm.operator()<std::vector<int>, std::vector<bool>>("rng::copy(vector<int>, std::vector<bool>)", std::ranges::copy);
6061
bm.operator()<std::deque<int>, std::vector<bool>>("rng::copy(deque<int>, std::vector<bool>)", std::ranges::copy);
6162
bm.operator()<std::list<int>, std::vector<bool>>("rng::copy(list<int>, std::vector<bool>)", std::ranges::copy);
63+
#endif
6264
}
6365

6466
// {std,ranges}::copy(vector<bool>)

libcxx/test/benchmarks/containers/sequence/sequence_container_benchmarks.h

+183-8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "benchmark/benchmark.h"
2323
#include "test_iterators.h"
2424
#include "../../GenerateInput.h"
25+
#include "../../../std/containers/from_range_helpers.h"
2526

2627
namespace support {
2728

@@ -172,8 +173,8 @@ void sequence_container_benchmarks(std::string container) {
172173
bool toggle = false;
173174
for ([[maybe_unused]] auto _ : st) {
174175
std::vector<ValueType>& in = toggle ? in1 : in2;
175-
auto first = in.data();
176-
auto last = in.data() + in.size();
176+
auto first = in.begin();
177+
auto last = in.end();
177178
c.assign(cpp17_input_iterator(first), cpp17_input_iterator(last));
178179
toggle = !toggle;
179180
DoNotOptimizeData(c);
@@ -237,8 +238,8 @@ void sequence_container_benchmarks(std::string container) {
237238
std::vector<ValueType> in;
238239
std::generate_n(std::back_inserter(in), size, gen);
239240
DoNotOptimizeData(in);
240-
auto first = in.data();
241-
auto last = in.data() + in.size();
241+
auto first = in.begin();
242+
auto last = in.end();
242243

243244
const int small = 100; // arbitrary
244245
Container c;
@@ -264,8 +265,8 @@ void sequence_container_benchmarks(std::string container) {
264265
std::vector<ValueType> in;
265266
std::generate_n(std::back_inserter(in), size, gen);
266267
DoNotOptimizeData(in);
267-
auto first = in.data();
268-
auto last = in.data() + in.size();
268+
auto first = in.begin();
269+
auto last = in.end();
269270

270271
const int overflow = size / 10; // 10% of elements won't fit in the vector when we insert
271272
Container c;
@@ -290,8 +291,8 @@ void sequence_container_benchmarks(std::string container) {
290291
std::vector<ValueType> in;
291292
std::generate_n(std::back_inserter(in), size, gen);
292293
DoNotOptimizeData(in);
293-
auto first = in.data();
294-
auto last = in.data() + in.size();
294+
auto first = in.begin();
295+
auto last = in.end();
295296

296297
auto const overflow = 9 * (size / 10); // 90% of elements won't fit in the vector when we insert
297298
Container c;
@@ -448,6 +449,180 @@ void sequence_container_benchmarks(std::string container) {
448449
}
449450
});
450451
}
452+
453+
////////////////////////////////////////////////////////////////////////////////////////////////
454+
// Additional benchmarks for vector<bool> iterator-pair and range-based operations
455+
////////////////////////////////////////////////////////////////////////////////////////////////
456+
457+
static constexpr bool is_vector_bool = requires {
458+
typename Container::allocator_type;
459+
} && std::same_as<std::remove_cvref_t<Container>, std::vector<bool, typename Container::allocator_type>>;
460+
461+
if constexpr (is_vector_bool) {
462+
auto bench_vb = [&](std::string operation, auto f) {
463+
benchmark::RegisterBenchmark(container + "::" + operation, f)->Arg(1024)->Arg(1 << 16)->Arg(1 << 20);
464+
};
465+
466+
{ // iterator-pair ctor
467+
auto bm = [&generators, &bench_vb, &tostr]<template <class> class Iter>(std::string iter) {
468+
for (auto gen : generators)
469+
bench_vb("ctor(" + iter + ", " + iter + ")" + tostr(gen), [gen](auto& st) {
470+
auto const size = st.range(0);
471+
std::vector<int> in;
472+
std::generate_n(std::back_inserter(in), size, gen);
473+
benchmark::DoNotOptimize(in);
474+
const auto begin = Iter(in.begin());
475+
const auto end = Iter(in.end());
476+
benchmark::DoNotOptimize(in);
477+
478+
for ([[maybe_unused]] auto _ : st) {
479+
Container c(begin, end); // we assume the destructor doesn't dominate the benchmark
480+
DoNotOptimizeData(c);
481+
}
482+
});
483+
};
484+
bm.template operator()<forward_iterator>("fwd_iter");
485+
bm.template operator()<random_access_iterator>("ra_iter");
486+
}
487+
{ // iterator-pair assignment
488+
auto bm = [&generators, &bench_vb, &tostr]<template <class> class Iter>(std::string iter) {
489+
for (auto gen : generators)
490+
bench_vb("assign(" + iter + ", " + iter + ")" + tostr(gen), [gen](auto& st) {
491+
auto const size = st.range(0);
492+
std::vector<int> in1, in2;
493+
std::generate_n(std::back_inserter(in1), size, gen);
494+
std::generate_n(std::back_inserter(in2), size, gen);
495+
DoNotOptimizeData(in1);
496+
DoNotOptimizeData(in2);
497+
498+
Container c(in1.begin(), in1.end());
499+
bool toggle = true;
500+
for ([[maybe_unused]] auto _ : st) {
501+
auto& in = toggle ? in2 : in1;
502+
c.assign(Iter(in.begin()), Iter(in.end()));
503+
toggle = !toggle;
504+
DoNotOptimizeData(c);
505+
}
506+
});
507+
};
508+
bm.template operator()<forward_iterator>("fwd_iter");
509+
bm.template operator()<random_access_iterator>("ra_iter");
510+
}
511+
{ // Iterator-pair insertion
512+
auto bm = [&generators, &bench_vb, &tostr]<template <class> class Iter>(std::string iter) {
513+
for (auto gen : generators)
514+
bench_vb("insert(begin, " + iter + ", " + iter + ")" + tostr(gen), [gen](auto& st) {
515+
auto const size = st.range(0);
516+
std::vector<int> in;
517+
Container c;
518+
std::generate_n(std::back_inserter(in), size, gen);
519+
std::generate_n(std::back_inserter(c), size, gen);
520+
DoNotOptimizeData(in);
521+
DoNotOptimizeData(c);
522+
523+
for ([[maybe_unused]] auto _ : st) {
524+
c.insert(c.begin(), Iter(in.begin()), Iter(in.end()));
525+
c.erase(c.begin() + size, c.end()); // avoid growing indefinitely
526+
DoNotOptimizeData(c);
527+
}
528+
});
529+
};
530+
bm.template operator()<forward_iterator>("fwd_iter");
531+
bm.template operator()<random_access_iterator>("ra_iter");
532+
}
533+
534+
#if defined(__cpp_lib_containers_ranges) && __cpp_lib_containers_ranges >= 202202L
535+
{ // Range-ctor
536+
auto bm = [&generators, &bench_vb, &tostr]<template <class, class> class Range>(std::string range) {
537+
for (auto gen : generators)
538+
bench_vb("ctor(" + range + ")" + tostr(gen), [gen](auto& st) {
539+
auto const size = st.range(0);
540+
std::vector<int> in;
541+
std::generate_n(std::back_inserter(in), size, gen);
542+
Range rg(std::ranges::begin(in), std::ranges::end(in));
543+
benchmark::DoNotOptimize(in);
544+
545+
for ([[maybe_unused]] auto _ : st) {
546+
Container c(std::from_range, rg); // we assume the destructor doesn't dominate the benchmark
547+
DoNotOptimizeData(c);
548+
}
549+
});
550+
};
551+
bm.template operator()<forward_range_wrapper>("fwd_range");
552+
bm.template operator()<random_access_range_wrapper>("ra_range");
553+
}
554+
{ // Range-assignment
555+
auto bm = [&generators, &bench_vb, &tostr]<template <class, class> class Range>(std::string range) {
556+
for (auto gen : generators)
557+
bench_vb("assign_range(" + range + ")" + tostr(gen), [gen](auto& st) {
558+
auto const size = st.range(0);
559+
std::vector<int> in1, in2;
560+
std::generate_n(std::back_inserter(in1), size, gen);
561+
std::generate_n(std::back_inserter(in2), size, gen);
562+
Range rg1(std::ranges::begin(in1), std::ranges::end(in1));
563+
Range rg2(std::ranges::begin(in2), std::ranges::end(in2));
564+
DoNotOptimizeData(in1);
565+
DoNotOptimizeData(in2);
566+
567+
Container c(std::from_range, rg1);
568+
bool toggle = true;
569+
for ([[maybe_unused]] auto _ : st) {
570+
auto& in = toggle ? rg2 : rg1;
571+
c.assign_range(in);
572+
toggle = !toggle;
573+
DoNotOptimizeData(c);
574+
}
575+
});
576+
};
577+
bm.template operator()<forward_range_wrapper>("fwd_range");
578+
bm.template operator()<random_access_range_wrapper>("ra_range");
579+
}
580+
{ // Range-insertion
581+
auto bm = [&generators, &bench_vb, &tostr]<template <class, class> class Range>(std::string range) {
582+
for (auto gen : generators)
583+
bench_vb("insert_range(" + range + ")" + tostr(gen), [gen](auto& st) {
584+
auto const size = st.range(0);
585+
std::vector<int> in;
586+
Container c;
587+
std::generate_n(std::back_inserter(in), size, gen);
588+
std::generate_n(std::back_inserter(c), size, gen);
589+
Range rg(std::ranges::begin(in), std::ranges::end(in));
590+
DoNotOptimizeData(in);
591+
DoNotOptimizeData(c);
592+
593+
for ([[maybe_unused]] auto _ : st) {
594+
c.insert_range(c.begin(), in);
595+
c.erase(c.begin() + size, c.end()); // avoid growing indefinitely
596+
DoNotOptimizeData(c);
597+
}
598+
});
599+
};
600+
bm.template operator()<forward_range_wrapper>("fwd_range");
601+
bm.template operator()<random_access_range_wrapper>("ra_range");
602+
}
603+
{ // Range-append
604+
auto bm = [&generators, &bench_vb, &tostr]<template <class, class> class Range>(std::string range) {
605+
for (auto gen : generators)
606+
bench_vb("append_range(" + range + ")" + tostr(gen), [gen](auto& st) {
607+
auto const size = st.range(0);
608+
std::vector<int> in;
609+
std::generate_n(std::back_inserter(in), size, gen);
610+
Range rg(std::ranges::begin(in), std::ranges::end(in));
611+
DoNotOptimizeData(in);
612+
613+
Container c;
614+
for ([[maybe_unused]] auto _ : st) {
615+
c.append_range(in);
616+
c.erase(c.begin(), c.end()); // avoid growing indefinitely
617+
DoNotOptimizeData(c);
618+
}
619+
});
620+
};
621+
bm.template operator()<forward_range_wrapper>("fwd_range");
622+
bm.template operator()<random_access_range_wrapper>("ra_range");
623+
}
624+
#endif
625+
}
451626
}
452627

453628
} // namespace support

libcxx/test/benchmarks/containers/sequence/vector.bench.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
int main(int argc, char** argv) {
1818
support::sequence_container_benchmarks<std::vector<int>>("std::vector<int>");
1919
support::sequence_container_benchmarks<std::vector<std::string>>("std::vector<std::string>");
20+
support::sequence_container_benchmarks<std::vector<bool>>("std::vector<bool>");
2021

2122
benchmark::Initialize(&argc, argv);
2223
benchmark::RunSpecifiedBenchmarks();

libcxx/test/benchmarks/containers/vector_bool_operations.bench.cpp

-110
This file was deleted.

0 commit comments

Comments
 (0)