[libcxx-commits] [libcxx] [libc++] ~vector: Don't __clear trivial typed elements (PR #86947)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Mar 28 05:53:13 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Johan Gardell (gardell)
<details>
<summary>Changes</summary>
I've been optimizing some code that streams large amounts of binary data using `std::vector<uint8_t>` and in the profiler I can see that the application spends a lot of time in `~vector()`, specifically `__clear()`.
For the `std::vector<bool>` specialization, `__clear` is not called when destructing the vector. I believe this is because `bool` is trivially destructible.
In this PR I propose a template specialization of `__destroy_vector` in the general `vector<T>` case that allows us to suppress the call to `__clear` if the element type in question is `is_trivially_destructible`.
Please let me know if I should clarify something. This is my first submission so I am sure I've gotten a lot of stuff wrong!
Regards
---
Full diff: https://github.com/llvm/llvm-project/pull/86947.diff
2 Files Affected:
- (modified) libcxx/include/vector (+10)
- (added) libcxx/test/std/containers/sequences/vector/vector.cons/dtor_no_trivial_element_dtor_call.pass.cpp (+85)
``````````diff
diff --git a/libcxx/include/vector b/libcxx/include/vector
index 0908482600c533..e0df865366103a 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -347,6 +347,7 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++
#include <__type_traits/is_allocator.h>
#include <__type_traits/is_constructible.h>
#include <__type_traits/is_nothrow_assignable.h>
+#include <__type_traits/is_trivially_destructible.h>
#include <__type_traits/noexcept_move_assign_container.h>
#include <__type_traits/type_identity.h>
#include <__utility/exception_guard.h>
@@ -486,6 +487,15 @@ private:
public:
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {}
+ template <typename _Tp2 = _Tp, __enable_if_t<is_trivially_destructible<_Tp2>::value, int> = 0>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
+ if (__vec_.__begin_ != nullptr) {
+ __vec_.__annotate_delete();
+ __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.capacity());
+ }
+ }
+
+ template <typename _Tp2 = _Tp, __enable_if_t<!is_trivially_destructible<_Tp2>::value, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
if (__vec_.__begin_ != nullptr) {
__vec_.__clear();
diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/dtor_no_trivial_element_dtor_call.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/dtor_no_trivial_element_dtor_call.pass.cpp
new file mode 100644
index 00000000000000..5a5399e2fffc68
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector/vector.cons/dtor_no_trivial_element_dtor_call.pass.cpp
@@ -0,0 +1,85 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+#include <cassert>
+
+struct int_alloc
+{
+ typedef int value_type;
+
+ template< class U >
+ struct rebind
+ {
+ typedef int_alloc other;
+ };
+
+ int* allocate(std::size_t n)
+ {
+ return new int[n];
+ }
+ void deallocate(int* p, std::size_t n)
+ {
+ for (std::size_t i = 0; i < n; ++i) {
+ assert(p[i] != 0);
+ }
+ delete p;
+ }
+};
+
+struct with_dtor
+{
+ with_dtor() = default;
+ with_dtor(const with_dtor &) = default;
+
+ int x = 42;
+
+ ~with_dtor() {
+ x = 0;
+ }
+};
+
+struct with_dtor_alloc
+{
+ typedef with_dtor value_type;
+
+ template< class U >
+ struct rebind
+ {
+ typedef with_dtor_alloc other;
+ };
+
+ with_dtor* allocate(std::size_t n)
+ {
+ return new with_dtor[n];
+ }
+ void deallocate(with_dtor* p, std::size_t n)
+ {
+ for (std::size_t i = 0; i < n; ++i) {
+ assert(p[i].x == 0);
+ }
+ delete[] p;
+ }
+};
+
+void tests()
+{
+ {
+ std::vector<with_dtor, with_dtor_alloc> v(5, with_dtor());
+ }
+ {
+ std::vector<int, int_alloc> v(5, 42);
+ }
+}
+
+int main(int, char**)
+{
+ tests();
+ return 0;
+}
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/86947
More information about the libcxx-commits
mailing list