[libcxx-commits] [libcxx] Optimize __assign_with_sentinel in std::vector (PR #113852)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Oct 27 19:17:25 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Peng Liu (winner245)

<details>
<summary>Changes</summary>

### Summary
This PR optimizes the `vector::__assign_with_sentinel` function by reusing existing memory more effectively, resulting in improved performance.

### Details
- **Memory Reuse**: The new implementation reuses the memory by directly assigning to the already initialized memory, instead of destructing all existing elements. Destruction now only occurs when the original vector has more elements than the input iterator range. By avoiding unnecessary destruction of existing elements, the new implementation potentially avoids memory deallocation for element types that maintain resources, allowing for memory reuse. This reduction in overhead leads to performance improvements. The new implementation is particularly beneficial for pre-populated vectors, resulting in 2.1x performance gains.

### Testing
Benchmark tests ([Quick-Bench Results](https://quick-bench.com/q/K8X6d3aR8s9DFixuRXGQR9zoGiM)) show significant performance improvements for test cases with pre-populated elements where the vector sizes are about the same before and after assignment:
- **1000 -> 1000**: ~2.1x faster
- **1000 -> 1**: roughly the same
- **1 -> 1000**: roughly the same

where `m -> n` represent the size change from m to n due to assignment. 

---
Full diff: https://github.com/llvm/llvm-project/pull/113852.diff


1 Files Affected:

- (modified) libcxx/include/__vector/vector.h (+8-3) 


``````````diff
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 7889e8c2201ac1..6c37c3113a536a 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -1031,9 +1031,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>

``````````

</details>


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


More information about the libcxx-commits mailing list