Skip to content

Commit c567e28

Browse files
authored
[libc++] Optimize vector<bool>::reserve (#170137)
Apple M4: ``` Benchmark old new Difference % Difference -------------------------------------------------------------------------- ------ ---------- ------------ -------------- vector<bool>(const_vector<bool>&) 12.73 12.87 0.14 1.07% vector<bool>(size_type,_const_value_type&) 9.39 9.41 0.02 0.22% vector<bool>(vector<bool>&&,_const_allocator_type&)_(different_allocators) 16.87 15.22 -1.65 -9.80% vector<bool>(vector<bool>&&,_const_allocator_type&)_(equal_allocators) 2.68 2.73 0.05 1.90% vector<bool>::reserve() 11.81 9.43 -2.38 -20.14% Geomean 9.14 8.62 -0.53 -5.76% ```
1 parent 8c21064 commit c567e28

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

libcxx/docs/ReleaseNotes/22.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Improvements and New Features
8484
``std::join_view<vector<vector<short>>>`` iterators.
8585
- ``std::atomic::wait`` has been refactored to accept more types to use platform native wait functions directly.
8686
This is guarded behind the ABI Macro ``_LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE``.
87+
- The performance of ``vector<bool>::reserve()`` has been improved by up to 2x.
8788

8889
- The ``num_get::do_get`` integral overloads have been optimized, resulting in a performance improvement of up to 2.8x.
8990

libcxx/include/__vector/vector_bool.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,8 @@ vector<bool, _Allocator>::vector(vector&& __v, const __type_identity_t<allocator
761761
__v.__cap_ = __v.__size_ = 0;
762762
} else if (__v.size() > 0) {
763763
__vallocate(__v.size());
764-
__construct_at_end(__v.begin(), __v.end(), __v.size());
764+
__size_ = __v.__size_;
765+
std::copy_n(__v.__begin_, __external_cap_to_internal(__v.size()), __begin_);
765766
}
766767
}
767768

@@ -856,7 +857,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::reserve(size_type _
856857
this->__throw_length_error();
857858
vector __v(this->get_allocator());
858859
__v.__vallocate(__n);
859-
__v.__construct_at_end(this->begin(), this->end(), this->size());
860+
__v.__size_ = __size_;
861+
std::copy_n(__begin_, __external_cap_to_internal(__size_), __v.__begin_);
860862
swap(__v);
861863
}
862864
}

libcxx/test/benchmarks/containers/sequence/vector_bool.bench.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
//===----------------------------------------------------------------------===//
88

99
#include <benchmark/benchmark.h>
10+
#include <memory_resource>
1011
#include <vector>
1112

13+
#include "test_macros.h"
14+
1215
static void BM_vector_bool_copy_ctor(benchmark::State& state) {
1316
std::vector<bool> vec(100, true);
1417

@@ -18,14 +21,51 @@ static void BM_vector_bool_copy_ctor(benchmark::State& state) {
1821
benchmark::DoNotOptimize(vec2);
1922
}
2023
}
21-
BENCHMARK(BM_vector_bool_copy_ctor);
24+
BENCHMARK(BM_vector_bool_copy_ctor)->Name("vector<bool>(const vector<bool>&)");
25+
26+
static void BM_vector_bool_move_ctor_alloc_equal(benchmark::State& state) {
27+
std::vector<bool> vec(100, true);
28+
29+
for (auto _ : state) {
30+
benchmark::DoNotOptimize(vec);
31+
std::vector<bool> vec2(std::move(vec), std::allocator<bool>());
32+
benchmark::DoNotOptimize(vec2);
33+
swap(vec, vec2);
34+
}
35+
}
36+
BENCHMARK(BM_vector_bool_move_ctor_alloc_equal)
37+
->Name("vector<bool>(vector<bool>&&, const allocator_type&) (equal allocators)");
38+
39+
#if TEST_STD_VER >= 17
40+
static void BM_vector_bool_move_ctor_alloc_different(benchmark::State& state) {
41+
std::pmr::monotonic_buffer_resource resource;
42+
std::pmr::vector<bool> vec(100, true, &resource);
43+
44+
for (auto _ : state) {
45+
benchmark::DoNotOptimize(vec);
46+
std::pmr::vector<bool> vec2(std::move(vec), std::pmr::new_delete_resource());
47+
benchmark::DoNotOptimize(vec2);
48+
}
49+
}
50+
BENCHMARK(BM_vector_bool_move_ctor_alloc_different)
51+
->Name("vector<bool>(vector<bool>&&, const allocator_type&) (different allocators)");
52+
#endif
2253

2354
static void BM_vector_bool_size_ctor(benchmark::State& state) {
2455
for (auto _ : state) {
2556
std::vector<bool> vec(100, true);
2657
benchmark::DoNotOptimize(vec);
2758
}
2859
}
29-
BENCHMARK(BM_vector_bool_size_ctor);
60+
BENCHMARK(BM_vector_bool_size_ctor)->Name("vector<bool>(size_type, const value_type&)");
61+
62+
static void BM_vector_bool_reserve(benchmark::State& state) {
63+
for (auto _ : state) {
64+
std::vector<bool> vec;
65+
vec.reserve(100);
66+
benchmark::DoNotOptimize(vec);
67+
}
68+
}
69+
BENCHMARK(BM_vector_bool_reserve)->Name("vector<bool>::reserve()");
3070

3171
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)