[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());
----------------
ldionne wrote:
This is not equivalent. In the current code, `a` and `b` are copies, let's say the elements are laid out like this in memory (`xN` are elements, `N` corresponds to the position that `xN` would occupy in a sorted sequence). Before sorting:
```
a = [x4 x2 x3 x5 x1] // allocation order is [x4 x2 x3 x5 x1]
b = [x4 x2 x3 x5 x1] // allocation order is [x4 x2 x3 x5 x1]
```
after sorting, we get:
```
a = [x1 x2 x3 x4 x5] // allocation order is [x4 x2 x3 x5 x1]
b = [x1 x2 x3 x4 x5] // allocation order is [x4 x2 x3 x5 x1]
```
So, with the current code, we get two equal and sorted sequences where the iteration order in the sequence *does not* match the allocation order.
If we take your edit, we get this instead. Before sorting:
```
a = [x4 x2 x3 x5 x1] // allocation order is [x4 x2 x3 x5 x1]
```
Then we sort and copy into `b`:
```
a = [x1 x2 x3 x4 x5] // allocation order is [x4 x2 x3 x5 x1]
b = [x1 x2 x3 x4 x5] // allocation order is [x1 x2 x3 x4 x5] <-- HERE
```
So we end up with `b` where the allocation order is the same as the iteration order. The idea behind this convoluted data generation was to avoid it. We can discuss whether it is worth doing, but that was the idea and that's why much of this data generation looks roundabout.
https://github.com/llvm/llvm-project/pull/214302
More information about the libcxx-commits
mailing list