[libcxx-commits] [libcxx] [libc++] Rewrite the set_intersection benchmark without CartesianBenchmarks (PR #214302)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Aug 10 05:06:31 PDT 2026


================
@@ -0,0 +1,209 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <set>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Each benchmarking scenario produces the two sorted ranges to intersect, with `n` the size of the
+// larger of the two. The size of the smaller range is derived from `n`, and the ratio between the
+// two appears in the benchmark's name. That ratio is used to exercise implementation choices that
+// make a difference when the two ranges have very different sizes.
+
+// Generate `n` random values and return two independently allocated sorted copies of them.
+//
+// The copy is made before sorting, so that the two copies don't end up with their out-of-line
+// storage laid out in the same order.
+template <class T>
+std::pair<std::vector<T>, std::vector<T>> two_sorted_copies(std::size_t n) {
+  std::vector<T> a(n);
+  std::generate_n(a.begin(), n, [] { return Generate<T>::random(); });
+  std::vector<T> b = a;
+  std::sort(a.begin(), a.end());
+  std::sort(b.begin(), b.end());
+  return std::make_pair(std::move(a), std::move(b));
+}
+
+// Generate two ranges where the larger range holds `n` elements and the smaller one holds every `ratio`th
+// element of it, so the whole smaller range matches and the matches are spread evenly through the larger
+// one. Whether searching within the larger range beats scanning it depends on how far apart the matches
+// are, which is why this scenario is instantiated with several ratios. With a ratio of 1 the two ranges
+// are identical, which is the worst case for the number of elements written to the output.
+template <class T>
+std::pair<std::vector<T>, std::vector<T>> spread(std::size_t n, std::size_t ratio) {
+  auto [large, sampled] = two_sorted_copies<T>(n);
----------------
ldionne wrote:

Similarly to the above, the goal here is to have two independent "data set" containers where the elements have been allocated not in iteration order. With the way this is currently written, we're `std::move`ing the elements (e.g. `string`s) into the sequences we're generating, which means that we maintain the memory location where the string was originally allocated (which we were careful not to make the same as iteration order).

https://github.com/llvm/llvm-project/pull/214302


More information about the libcxx-commits mailing list