[libcxx-commits] [libcxx] Optimize vector::assign for InputIterator-only pair inputs (PR #113852)

Peng Liu via libcxx-commits libcxx-commits at lists.llvm.org
Thu Nov 28 08:16:23 PST 2024


https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/113852

>From a7aa7c57efa11e058e548f51f0a6d2386e281add Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Sun, 27 Oct 2024 17:03:28 -0400
Subject: [PATCH 1/8] Improve __assign_with_sentinel in std::vector

---
 libcxx/include/__vector/vector.h | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 4b9ba24e97f65e..16033f026f6457 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -1003,9 +1003,14 @@ template <class _Tp, class _Allocator>
 template <class _Iterator, class _Sentinel>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
 vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
-  clear();
-  for (; __first != __last; ++__first)
-    emplace_back(*__first);
+  pointer __cur = __begin_;
+  for (; __first != __last && __cur != __end_; ++__cur, ++__first)
+    *__cur = *__first;
+  if (__cur != __end_)
+    __destruct_at_end(__cur);
+  else
+    for (; __first != __last; ++__first)
+      emplace_back(*__first);
 }
 
 template <class _Tp, class _Allocator>

>From 75eab998a6d1b686d494fb42f24e76c9a89ded12 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 6 Nov 2024 22:54:20 -0500
Subject: [PATCH 2/8] Avoid invoking operator,

---
 libcxx/include/__vector/vector.h              |  2 +-
 libcxx/test/benchmarks/ContainerBenchmarks.h  | 70 +++++++++++++++++++
 libcxx/test/benchmarks/GenerateInput.h        |  8 +++
 .../benchmarks/vector_operations.bench.cpp    |  6 ++
 4 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 16033f026f6457..22bb71175cd416 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -1004,7 +1004,7 @@ template <class _Iterator, class _Sentinel>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
 vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
   pointer __cur = __begin_;
-  for (; __first != __last && __cur != __end_; ++__cur, ++__first)
+  for (; __first != __last && __cur != __end_; ++__first, (void)++__cur)
     *__cur = *__first;
   if (__cur != __end_)
     __destruct_at_end(__cur);
diff --git a/libcxx/test/benchmarks/ContainerBenchmarks.h b/libcxx/test/benchmarks/ContainerBenchmarks.h
index 38e11777f488b7..cfee480d3a77c4 100644
--- a/libcxx/test/benchmarks/ContainerBenchmarks.h
+++ b/libcxx/test/benchmarks/ContainerBenchmarks.h
@@ -50,6 +50,76 @@ void BM_Assignment(benchmark::State& st, Container) {
   }
 }
 
+// Wrap any Iterator into an input iterator
+template <typename Iterator>
+class InputIterator {
+  using iter_traits = std::iterator_traits<Iterator>;
+
+public:
+  using iterator_category = std::input_iterator_tag;
+  using value_type        = typename iter_traits::value_type;
+  using difference_type   = typename iter_traits::difference_type;
+  using pointer           = typename iter_traits::pointer;
+  using reference         = typename iter_traits::reference;
+
+  InputIterator(Iterator it) : current_(it) {}
+
+  reference operator*() { return *current_; }
+  InputIterator& operator++() {
+    ++current_;
+    return *this;
+  }
+  InputIterator operator++(int) {
+    InputIterator tmp = *this;
+    ++(*this);
+    return tmp;
+  }
+
+  friend bool operator==(const InputIterator& lhs, const InputIterator& rhs) { return lhs.current_ == rhs.current_; }
+  friend bool operator!=(const InputIterator& lhs, const InputIterator& rhs) { return !(lhs == rhs); }
+
+private:
+  Iterator current_;
+};
+
+template <typename Iterator>
+InputIterator<Iterator> make_input_iterator(Iterator it) {
+  return InputIterator<Iterator>(it);
+}
+
+template <class Container,
+          class GenInputs,
+          typename std::enable_if<std::is_trivial<typename Container::value_type>::value>::type* = nullptr>
+void BM_AssignInputIterIter(benchmark::State& st, Container c, GenInputs gen) {
+  auto in = gen(st.range(1));
+  benchmark::DoNotOptimize(&in);
+  for (auto _ : st) {
+    st.PauseTiming();
+    c.resize(st.range(0));
+    benchmark::DoNotOptimize(&c);
+    st.ResumeTiming();
+    c.assign(make_input_iterator(in.begin()), make_input_iterator(in.end()));
+    benchmark::ClobberMemory();
+  }
+}
+
+template <class Container,
+          class GenInputs,
+          typename std::enable_if<!std::is_trivial<typename Container::value_type>::value>::type* = nullptr>
+void BM_AssignInputIterIter(benchmark::State& st, Container c, GenInputs gen) {
+  auto v  = gen(1, 100);
+  auto in = gen(st.range(1), 32);
+  benchmark::DoNotOptimize(&in);
+  for (auto _ : st) {
+    st.PauseTiming();
+    c.resize(st.range(0), v[0]);
+    benchmark::DoNotOptimize(&c);
+    st.ResumeTiming();
+    c.assign(make_input_iterator(in.begin()), make_input_iterator(in.end()));
+    benchmark::ClobberMemory();
+  }
+}
+
 template <class Container>
 void BM_ConstructSizeValue(benchmark::State& st, Container, typename Container::value_type const& val) {
   const auto size = st.range(0);
diff --git a/libcxx/test/benchmarks/GenerateInput.h b/libcxx/test/benchmarks/GenerateInput.h
index db376614382bc4..d96a02c4b7c001 100644
--- a/libcxx/test/benchmarks/GenerateInput.h
+++ b/libcxx/test/benchmarks/GenerateInput.h
@@ -121,6 +121,14 @@ inline std::vector<std::string> getRandomStringInputs(std::size_t N) {
   return inputs;
 }
 
+inline std::vector<std::string> getRandomStringInputsWithLength(std::size_t N, std::size_t len) {
+  std::vector<std::string> inputs;
+  inputs.reserve(N);
+  for (size_t i = 0; i < N; ++i)
+    inputs.push_back(getRandomString(len));
+  return inputs;
+}
+
 inline std::vector<std::string> getPrefixedRandomStringInputs(std::size_t N) {
   std::vector<std::string> inputs;
   inputs.reserve(N);
diff --git a/libcxx/test/benchmarks/vector_operations.bench.cpp b/libcxx/test/benchmarks/vector_operations.bench.cpp
index 1855861263324d..a51944ac06e90f 100644
--- a/libcxx/test/benchmarks/vector_operations.bench.cpp
+++ b/libcxx/test/benchmarks/vector_operations.bench.cpp
@@ -79,4 +79,10 @@ BENCHMARK(bm_grow<std::string>);
 BENCHMARK(bm_grow<std::unique_ptr<int>>);
 BENCHMARK(bm_grow<std::deque<int>>);
 
+BENCHMARK_CAPTURE(BM_AssignInputIterIter, vector_int, std::vector<int>{}, getRandomIntegerInputs<int>)
+    ->Args({TestNumInputs, TestNumInputs});
+
+BENCHMARK_CAPTURE(BM_AssignInputIterIter, vector_string, std::vector<std::string>{}, getRandomStringInputsWithLength)
+    ->Args({TestNumInputs, TestNumInputs});
+
 BENCHMARK_MAIN();

>From c131b5c824fde90d737bca17236634740093eee3 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Mon, 11 Nov 2024 14:19:10 -0500
Subject: [PATCH 3/8] Add release note to this optimization in 20.rst

---
 libcxx/docs/ReleaseNotes/20.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index 93d45f508d5ffe..433aa45bce5d5c 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -69,6 +69,10 @@ Improvements and New Features
 - The ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY`` ABI configuration was added, which allows storing valid bounds
   in ``std::array::iterator`` and detecting OOB accesses when the appropriate hardening mode is enabled.
 
+- The `assign(_InputIterator, _InputIterator)` function of `std::vector<_Tp, _Allocator>` has been optimized for
+  non-trivial element types, such as `std::vector<std::string>`, with a performance improvement of up to 2.3x. The
+  performance for trivial types, such as `std::vector<int>`, remains similar or shows slight improvements.
+
 Deprecations and Removals
 -------------------------
 

>From 52121aff311b0070d12fe67b25df8191ce3bc79b Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Tue, 12 Nov 2024 10:59:11 -0500
Subject: [PATCH 4/8] Restructure benchmark tests

---
 libcxx/test/benchmarks/ContainerBenchmarks.h  | 56 +++----------------
 libcxx/test/benchmarks/GenerateInput.h        | 13 ++++-
 .../benchmarks/vector_operations.bench.cpp    |  4 ++
 3 files changed, 23 insertions(+), 50 deletions(-)

diff --git a/libcxx/test/benchmarks/ContainerBenchmarks.h b/libcxx/test/benchmarks/ContainerBenchmarks.h
index cfee480d3a77c4..ba025e93753459 100644
--- a/libcxx/test/benchmarks/ContainerBenchmarks.h
+++ b/libcxx/test/benchmarks/ContainerBenchmarks.h
@@ -14,8 +14,9 @@
 #include <iterator>
 #include <utility>
 
-#include "Utilities.h"
 #include "benchmark/benchmark.h"
+#include "Utilities.h"
+#include "test_iterators.h"
 
 namespace ContainerBenchmarks {
 
@@ -50,55 +51,16 @@ void BM_Assignment(benchmark::State& st, Container) {
   }
 }
 
-// Wrap any Iterator into an input iterator
-template <typename Iterator>
-class InputIterator {
-  using iter_traits = std::iterator_traits<Iterator>;
-
-public:
-  using iterator_category = std::input_iterator_tag;
-  using value_type        = typename iter_traits::value_type;
-  using difference_type   = typename iter_traits::difference_type;
-  using pointer           = typename iter_traits::pointer;
-  using reference         = typename iter_traits::reference;
-
-  InputIterator(Iterator it) : current_(it) {}
-
-  reference operator*() { return *current_; }
-  InputIterator& operator++() {
-    ++current_;
-    return *this;
-  }
-  InputIterator operator++(int) {
-    InputIterator tmp = *this;
-    ++(*this);
-    return tmp;
-  }
-
-  friend bool operator==(const InputIterator& lhs, const InputIterator& rhs) { return lhs.current_ == rhs.current_; }
-  friend bool operator!=(const InputIterator& lhs, const InputIterator& rhs) { return !(lhs == rhs); }
-
-private:
-  Iterator current_;
-};
-
-template <typename Iterator>
-InputIterator<Iterator> make_input_iterator(Iterator it) {
-  return InputIterator<Iterator>(it);
-}
-
 template <class Container,
           class GenInputs,
           typename std::enable_if<std::is_trivial<typename Container::value_type>::value>::type* = nullptr>
 void BM_AssignInputIterIter(benchmark::State& st, Container c, GenInputs gen) {
   auto in = gen(st.range(1));
+  c.resize(st.range(0));
   benchmark::DoNotOptimize(&in);
+  benchmark::DoNotOptimize(&c);
   for (auto _ : st) {
-    st.PauseTiming();
-    c.resize(st.range(0));
-    benchmark::DoNotOptimize(&c);
-    st.ResumeTiming();
-    c.assign(make_input_iterator(in.begin()), make_input_iterator(in.end()));
+    c.assign(cpp17_input_iterator(in.begin()), cpp17_input_iterator(in.end()));
     benchmark::ClobberMemory();
   }
 }
@@ -108,14 +70,12 @@ template <class Container,
           typename std::enable_if<!std::is_trivial<typename Container::value_type>::value>::type* = nullptr>
 void BM_AssignInputIterIter(benchmark::State& st, Container c, GenInputs gen) {
   auto v  = gen(1, 100);
+  c.resize(st.range(0), v[0]);
   auto in = gen(st.range(1), 32);
   benchmark::DoNotOptimize(&in);
+  benchmark::DoNotOptimize(&c);
   for (auto _ : st) {
-    st.PauseTiming();
-    c.resize(st.range(0), v[0]);
-    benchmark::DoNotOptimize(&c);
-    st.ResumeTiming();
-    c.assign(make_input_iterator(in.begin()), make_input_iterator(in.end()));
+    c.assign(cpp17_input_iterator(in.begin()), cpp17_input_iterator(in.end()));
     benchmark::ClobberMemory();
   }
 }
diff --git a/libcxx/test/benchmarks/GenerateInput.h b/libcxx/test/benchmarks/GenerateInput.h
index d96a02c4b7c001..72b12bae9fe085 100644
--- a/libcxx/test/benchmarks/GenerateInput.h
+++ b/libcxx/test/benchmarks/GenerateInput.h
@@ -121,14 +121,23 @@ inline std::vector<std::string> getRandomStringInputs(std::size_t N) {
   return inputs;
 }
 
-inline std::vector<std::string> getRandomStringInputsWithLength(std::size_t N, std::size_t len) {
+inline std::vector<std::string> getRandomStringInputsWithLength(std::size_t N, std::size_t len) { // N-by-len
   std::vector<std::string> inputs;
   inputs.reserve(N);
-  for (size_t i = 0; i < N; ++i)
+  for (std::size_t i = 0; i < N; ++i)
     inputs.push_back(getRandomString(len));
   return inputs;
 }
 
+template <class IntT>
+inline std::vector<std::vector<IntT>> getRandomIntegerInputsWithLength(std::size_t N, std::size_t len) { // N-by-len
+  std::vector<std::vector<IntT>> inputs;
+  inputs.reserve(N);
+  for (std::size_t i = 0; i < N; ++i)
+    inputs.push_back(getRandomIntegerInputs<IntT>(len));
+  return inputs;
+}
+
 inline std::vector<std::string> getPrefixedRandomStringInputs(std::size_t N) {
   std::vector<std::string> inputs;
   inputs.reserve(N);
diff --git a/libcxx/test/benchmarks/vector_operations.bench.cpp b/libcxx/test/benchmarks/vector_operations.bench.cpp
index a51944ac06e90f..b4e8bc5dcc2fc8 100644
--- a/libcxx/test/benchmarks/vector_operations.bench.cpp
+++ b/libcxx/test/benchmarks/vector_operations.bench.cpp
@@ -85,4 +85,8 @@ BENCHMARK_CAPTURE(BM_AssignInputIterIter, vector_int, std::vector<int>{}, getRan
 BENCHMARK_CAPTURE(BM_AssignInputIterIter, vector_string, std::vector<std::string>{}, getRandomStringInputsWithLength)
     ->Args({TestNumInputs, TestNumInputs});
 
+BENCHMARK_CAPTURE(
+    BM_AssignInputIterIter, vector_vector_int, std::vector<std::vector<int>>{}, getRandomIntegerInputsWithLength<int>)
+    ->Args({TestNumInputs, TestNumInputs});
+
 BENCHMARK_MAIN();

>From 08abdb1ab99fe18bf52f49e1c1914776ce7a0c01 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Tue, 12 Nov 2024 11:26:33 -0500
Subject: [PATCH 5/8] Run clang-format

---
 libcxx/include/__vector/vector.h             | 5 +++--
 libcxx/test/benchmarks/ContainerBenchmarks.h | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 22bb71175cd416..6ba7ba7bcf724b 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -1006,11 +1006,12 @@ vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __l
   pointer __cur = __begin_;
   for (; __first != __last && __cur != __end_; ++__first, (void)++__cur)
     *__cur = *__first;
-  if (__cur != __end_)
+  if (__cur != __end_) {
     __destruct_at_end(__cur);
-  else
+  } else {
     for (; __first != __last; ++__first)
       emplace_back(*__first);
+  }
 }
 
 template <class _Tp, class _Allocator>
diff --git a/libcxx/test/benchmarks/ContainerBenchmarks.h b/libcxx/test/benchmarks/ContainerBenchmarks.h
index ba025e93753459..f1d41e92d22413 100644
--- a/libcxx/test/benchmarks/ContainerBenchmarks.h
+++ b/libcxx/test/benchmarks/ContainerBenchmarks.h
@@ -69,7 +69,7 @@ template <class Container,
           class GenInputs,
           typename std::enable_if<!std::is_trivial<typename Container::value_type>::value>::type* = nullptr>
 void BM_AssignInputIterIter(benchmark::State& st, Container c, GenInputs gen) {
-  auto v  = gen(1, 100);
+  auto v = gen(1, 100);
   c.resize(st.range(0), v[0]);
   auto in = gen(st.range(1), 32);
   benchmark::DoNotOptimize(&in);

>From c9c6fb9a1ed197624d4a858367aba2e4d3104005 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 13 Nov 2024 22:42:00 -0500
Subject: [PATCH 6/8] Update release note

---
 libcxx/docs/ReleaseNotes/20.rst | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index 433aa45bce5d5c..a5ff6cb926751f 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -69,9 +69,8 @@ Improvements and New Features
 - The ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY`` ABI configuration was added, which allows storing valid bounds
   in ``std::array::iterator`` and detecting OOB accesses when the appropriate hardening mode is enabled.
 
-- The `assign(_InputIterator, _InputIterator)` function of `std::vector<_Tp, _Allocator>` has been optimized for
-  non-trivial element types, such as `std::vector<std::string>`, with a performance improvement of up to 2.3x. The
-  performance for trivial types, such as `std::vector<int>`, remains similar or shows slight improvements.
+- The input iterator overload of `assign(_InputIterator, _InputIterator)` in `std::vector<_Tp, _Allocator>` has been 
+  optimized, resulting in a performance improvement of up to 3.7x.
 
 Deprecations and Removals
 -------------------------

>From 91eb3bec2c9d2fc8655ae3fb6686283a3645a119 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Fri, 15 Nov 2024 14:27:42 -0500
Subject: [PATCH 7/8] Refactor tests

---
 libcxx/docs/ReleaseNotes/20.rst               |  5 +++--
 libcxx/test/benchmarks/ContainerBenchmarks.h  | 22 +++----------------
 .../benchmarks/vector_operations.bench.cpp    |  9 +++++---
 3 files changed, 12 insertions(+), 24 deletions(-)

diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index a5ff6cb926751f..a72fd2d5db9e26 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -69,8 +69,9 @@ Improvements and New Features
 - The ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY`` ABI configuration was added, which allows storing valid bounds
   in ``std::array::iterator`` and detecting OOB accesses when the appropriate hardening mode is enabled.
 
-- The input iterator overload of `assign(_InputIterator, _InputIterator)` in `std::vector<_Tp, _Allocator>` has been 
-  optimized, resulting in a performance improvement of up to 3.7x.
+- The input iterator overload of `assign(_InputIterator, _InputIterator)` in `std::vector<_Tp, _Allocator>` has been
+  optimized, resulting in a performance improvement of up to 2x for trivial element types (e.g., `std::vector<int>`),
+  and up to 3.4x for non-trivial element types (e.g., `std::vector<std::vector<int>>`).
 
 Deprecations and Removals
 -------------------------
diff --git a/libcxx/test/benchmarks/ContainerBenchmarks.h b/libcxx/test/benchmarks/ContainerBenchmarks.h
index f1d41e92d22413..458134c8191d12 100644
--- a/libcxx/test/benchmarks/ContainerBenchmarks.h
+++ b/libcxx/test/benchmarks/ContainerBenchmarks.h
@@ -51,27 +51,11 @@ void BM_Assignment(benchmark::State& st, Container) {
   }
 }
 
-template <class Container,
-          class GenInputs,
-          typename std::enable_if<std::is_trivial<typename Container::value_type>::value>::type* = nullptr>
+template <std::size_t... sz, typename Container, typename GenInputs>
 void BM_AssignInputIterIter(benchmark::State& st, Container c, GenInputs gen) {
-  auto in = gen(st.range(1));
-  c.resize(st.range(0));
-  benchmark::DoNotOptimize(&in);
-  benchmark::DoNotOptimize(&c);
-  for (auto _ : st) {
-    c.assign(cpp17_input_iterator(in.begin()), cpp17_input_iterator(in.end()));
-    benchmark::ClobberMemory();
-  }
-}
-
-template <class Container,
-          class GenInputs,
-          typename std::enable_if<!std::is_trivial<typename Container::value_type>::value>::type* = nullptr>
-void BM_AssignInputIterIter(benchmark::State& st, Container c, GenInputs gen) {
-  auto v = gen(1, 100);
+  auto v = gen(1, sz...);
   c.resize(st.range(0), v[0]);
-  auto in = gen(st.range(1), 32);
+  auto in = gen(st.range(1), sz...);
   benchmark::DoNotOptimize(&in);
   benchmark::DoNotOptimize(&c);
   for (auto _ : st) {
diff --git a/libcxx/test/benchmarks/vector_operations.bench.cpp b/libcxx/test/benchmarks/vector_operations.bench.cpp
index b4e8bc5dcc2fc8..ea6876c6cad268 100644
--- a/libcxx/test/benchmarks/vector_operations.bench.cpp
+++ b/libcxx/test/benchmarks/vector_operations.bench.cpp
@@ -82,11 +82,14 @@ BENCHMARK(bm_grow<std::deque<int>>);
 BENCHMARK_CAPTURE(BM_AssignInputIterIter, vector_int, std::vector<int>{}, getRandomIntegerInputs<int>)
     ->Args({TestNumInputs, TestNumInputs});
 
-BENCHMARK_CAPTURE(BM_AssignInputIterIter, vector_string, std::vector<std::string>{}, getRandomStringInputsWithLength)
+BENCHMARK_CAPTURE(
+    BM_AssignInputIterIter<32>, vector_string, std::vector<std::string>{}, getRandomStringInputsWithLength)
     ->Args({TestNumInputs, TestNumInputs});
 
-BENCHMARK_CAPTURE(
-    BM_AssignInputIterIter, vector_vector_int, std::vector<std::vector<int>>{}, getRandomIntegerInputsWithLength<int>)
+BENCHMARK_CAPTURE(BM_AssignInputIterIter<100>,
+                  vector_vector_int,
+                  std::vector<std::vector<int>>{},
+                  getRandomIntegerInputsWithLength<int>)
     ->Args({TestNumInputs, TestNumInputs});
 
 BENCHMARK_MAIN();

>From 4fa53ef65532d36f2f3d7aad447ab0a8fe627244 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Thu, 28 Nov 2024 11:14:44 -0500
Subject: [PATCH 8/8] Rebase and a little refactor

---
 libcxx/test/benchmarks/GenerateInput.h        | 22 ++++++++-----------
 .../benchmarks/vector_operations.bench.cpp    |  1 -
 2 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/libcxx/test/benchmarks/GenerateInput.h b/libcxx/test/benchmarks/GenerateInput.h
index 72b12bae9fe085..67ce798071eaa4 100644
--- a/libcxx/test/benchmarks/GenerateInput.h
+++ b/libcxx/test/benchmarks/GenerateInput.h
@@ -108,29 +108,25 @@ std::vector<IntT> getRandomIntegerInputs(std::size_t N) {
   return inputs;
 }
 
-inline std::vector<std::string> getDuplicateStringInputs(std::size_t N) {
-  std::vector<std::string> inputs(N, getRandomString(1024));
-  return inputs;
-}
-
-inline std::vector<std::string> getRandomStringInputs(std::size_t N) {
+inline std::vector<std::string> getRandomStringInputsWithLength(std::size_t N, std::size_t len) { // N-by-len
   std::vector<std::string> inputs;
   inputs.reserve(N);
   for (std::size_t i = 0; i < N; ++i)
-    inputs.push_back(getRandomString(1024));
+    inputs.push_back(getRandomString(len));
   return inputs;
 }
 
-inline std::vector<std::string> getRandomStringInputsWithLength(std::size_t N, std::size_t len) { // N-by-len
-  std::vector<std::string> inputs;
-  inputs.reserve(N);
-  for (std::size_t i = 0; i < N; ++i)
-    inputs.push_back(getRandomString(len));
+inline std::vector<std::string> getDuplicateStringInputs(std::size_t N) {
+  std::vector<std::string> inputs(N, getRandomString(1024));
   return inputs;
 }
 
+inline std::vector<std::string> getRandomStringInputs(std::size_t N) {
+  return getRandomStringInputsWithLength(N, 1024);
+}
+
 template <class IntT>
-inline std::vector<std::vector<IntT>> getRandomIntegerInputsWithLength(std::size_t N, std::size_t len) { // N-by-len
+std::vector<std::vector<IntT>> getRandomIntegerInputsWithLength(std::size_t N, std::size_t len) { // N-by-len
   std::vector<std::vector<IntT>> inputs;
   inputs.reserve(N);
   for (std::size_t i = 0; i < N; ++i)
diff --git a/libcxx/test/benchmarks/vector_operations.bench.cpp b/libcxx/test/benchmarks/vector_operations.bench.cpp
index ea6876c6cad268..3a72eaec4dd57e 100644
--- a/libcxx/test/benchmarks/vector_operations.bench.cpp
+++ b/libcxx/test/benchmarks/vector_operations.bench.cpp
@@ -18,7 +18,6 @@
 #include <vector>
 
 #include "benchmark/benchmark.h"
-
 #include "ContainerBenchmarks.h"
 #include "GenerateInput.h"
 



More information about the libcxx-commits mailing list