diff --git a/libcxx/include/__algorithm/find.h b/libcxx/include/__algorithm/find.h index 5f32ae8fc9524..91c6a4e744a71 100644 --- a/libcxx/include/__algorithm/find.h +++ b/libcxx/include/__algorithm/find.h @@ -228,7 +228,8 @@ struct __find_segment { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _InputIterator operator()(_InputIterator __first, _InputIterator __last, _Proj& __proj) const { - return std::__find(__first, __last, __value_, __proj); + return std::__rewrap_iter( + __first, std::__find(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __value_, __proj)); } }; diff --git a/libcxx/test/benchmarks/algorithms/nonmodifying/find.bench.cpp b/libcxx/test/benchmarks/algorithms/nonmodifying/find.bench.cpp index afea31fb59e95..7780b5a92a6c4 100644 --- a/libcxx/test/benchmarks/algorithms/nonmodifying/find.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/nonmodifying/find.bench.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -83,6 +84,20 @@ int main(int argc, char** argv) { bm.template operator()>("rng::find_if_not(list) (" + comment + ")", ranges_find_if_not); }; + auto register_nested_container_benchmarks = [&](auto bm, std::string comment) { + // ranges_find + bm.template operator()>>( + "rng::find(join_view(vector>)) (" + comment + ")", ranges_find); + bm.template operator()>>( + "rng::find(join_view(vector>)) (" + comment + ")", ranges_find); + bm.template operator()>>( + "rng::find(join_view(list>)) (" + comment + ")", ranges_find); + bm.template operator()>>( + "rng::find(join_view(vector>)) (" + comment + ")", ranges_find); + bm.template operator()>>( + "rng::find(join_view(deque>)) (" + comment + ")", ranges_find); + }; + // Benchmark {std,ranges}::{find,find_if,find_if_not}(normal container) where we // bail out after 25% of elements { @@ -142,6 +157,44 @@ int main(int argc, char** argv) { register_benchmarks(bm, "process all"); } + // Benchmark {std,ranges}::{find,find_if,find_if_not}(join(normal container)) where we process the whole sequence + { + auto bm = [](std::string name, auto find) { + benchmark::RegisterBenchmark( + name, + [find](auto& st) { + std::size_t const size = st.range(0); + std::size_t const seg_size = 256; + std::size_t const segments = (size + seg_size - 1) / seg_size; + using C1 = typename Container::value_type; + using ValueType = typename C1::value_type; + ValueType x = Generate::random(); + ValueType y = random_different_from({x}); + Container c(segments); + auto n = size; + for (auto it = c.begin(); it != c.end(); it++) { + it->resize(std::min(seg_size, n), x); + n -= it->size(); + } + + auto view = c | std::views::join; + + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(c); + benchmark::DoNotOptimize(y); + auto result = find(view.begin(), view.end(), y); + benchmark::DoNotOptimize(result); + } + }) + ->Arg(8) + ->Arg(50) // non power-of-two + ->Arg(1024) + ->Arg(8192) + ->Arg(1 << 15); + }; + register_nested_container_benchmarks(bm, "process all"); + } + // Benchmark {std,ranges}::{find,find_if,find_if_not}(vector) where we process the whole sequence { auto bm = [](std::string name, auto find) {