Connector Switch
2d106844e7
[libcxx] Optimize ranges::fold_left_with_iter for segmented iterators ( #177853 )
...
Part of https://github.com/llvm/llvm-project/issues/102817 .
This patch attempts to optimize the performance of
`ranges::fold_left_with_iter` for segmented iterators.
- before
```
# | rng::fold_left(vector<int>)/8 2.78 ns 2.78 ns 241953718
# | rng::fold_left(vector<int>)/32 12.2 ns 12.2 ns 57579851
# | rng::fold_left(vector<int>)/50 19.2 ns 19.2 ns 36487764
# | rng::fold_left(vector<int>)/8192 3226 ns 3226 ns 216811
# | rng::fold_left(vector<int>)/1048576 441842 ns 441839 ns 1592
# | rng::fold_left(deque<int>)/8 2.83 ns 2.83 ns 243888678
# | rng::fold_left(deque<int>)/32 16.6 ns 16.6 ns 42297458
# | rng::fold_left(deque<int>)/50 22.3 ns 22.3 ns 31387998
# | rng::fold_left(deque<int>)/8192 2492 ns 2492 ns 281637
# | rng::fold_left(deque<int>)/1048576 324936 ns 324936 ns 2154
# | rng::fold_left(list<int>)/8 2.54 ns 2.54 ns 275946635
# | rng::fold_left(list<int>)/32 16.2 ns 16.2 ns 42901634
# | rng::fold_left(list<int>)/50 54.7 ns 54.7 ns 12767450
# | rng::fold_left(list<int>)/8192 15154 ns 15154 ns 56744
# | rng::fold_left(list<int>)/1048576 4976906 ns 4976867 ns 158
```
- after
```
# | rng::fold_left(vector<int>)/8 2.74 ns 2.74 ns 255954900
# | rng::fold_left(vector<int>)/32 12.1 ns 12.1 ns 57843462
# | rng::fold_left(vector<int>)/50 19.2 ns 19.2 ns 36422594
# | rng::fold_left(vector<int>)/8192 3202 ns 3202 ns 218265
# | rng::fold_left(vector<int>)/1048576 435718 ns 435709 ns 1609
# | rng::fold_left(deque<int>)/8 2.52 ns 2.52 ns 277288254
# | rng::fold_left(deque<int>)/32 14.1 ns 14.1 ns 52244463
# | rng::fold_left(deque<int>)/50 16.2 ns 16.2 ns 43131857
# | rng::fold_left(deque<int>)/8192 1695 ns 1695 ns 415620
# | rng::fold_left(deque<int>)/1048576 277729 ns 277731 ns 2532
# | rng::fold_left(list<int>)/8 2.55 ns 2.55 ns 277025050
# | rng::fold_left(list<int>)/32 16.2 ns 16.2 ns 43058857
# | rng::fold_left(list<int>)/50 54.7 ns 54.7 ns 12705516
# | rng::fold_left(list<int>)/8192 15236 ns 15235 ns 56840
# | rng::fold_left(list<int>)/1048576 4827263 ns 4827147 ns 152
```
2026-02-05 21:12:36 +08:00
sohail
9bde15d76d
[libc++] Deprecate std::launch::any extension ( #173397 )
...
`std::launch::any` was a draft C++11 feature that was removed before the
final standard but it has remained in libc++ as an extension. This patch
marks it as deprecated and suggests using `std::launch::async |
std::launch::deferred` instead.
- Used `_LIBCPP_DEPRECATED_` to mark `std::launch::any` as deprecated
with an associated warning message recommending `std::launch::async |
std::launch::deferred` instead.
- Added a `.verify.cpp` test to validate the deprecation warning.
- Updated existing tests to avoid using the deprecated extension.
- Added note about deprecation in docs.
Fixes #173219
---------
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2026-01-30 13:51:52 +08:00
xiaoyang-sde
9311996261
[libc++][ranges] implement ranges::shift_left ( #83231 )
...
Implement the `ranges::shift_left` algorithm from
[P2440R1](https://wg21.link/P2440R1 ).
Closes : #134061
---------
Co-authored-by: Hui Xie <hui.xie1990@gmail.com>
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2026-01-25 10:35:43 +00:00
Hui
985d75a57a
[libc++] define FTM __cpp_lib_ranges_zip ( #176569 )
...
P2321R2 has been implemented in various PRs. Based on the discussion
in #105169 , the last bit in iterator.concept.winc doesn't require
any changes, so we can actually mark this as done.
Fixes #105169
2026-01-19 15:18:57 -05:00
Louis Dionne
ec983ad611
[runtimes] Post-branch tasks for the LLVM 23 release ( #176007 )
...
This performs most of the post-branch tasks to start working on the LLVM
23 release. Things that are left to do:
- Update the unicode version
- Update CI versions and supported compiler versions
2026-01-14 18:39:02 +00:00
Nikolas Klauser
89c8a253d7
[libc++] Make optional::iterator experimental ( #173470 )
...
We haven't yet decided what we want the `optional::iterator` type to be
in the end, so let's make it experimental for now so that we don't
commit to an ABI yet.
2026-01-09 10:21:48 -05:00
Nikolas Klauser
b6bfb199cc
[libc++] Fix {deque,vector}::append_range assuming too much about the types ( #162438 )
...
Currently, `deque` and `vector`'s `append_range` is implemented in terms
of `insert_range`. The problem with that is that `insert_range` has more
preconditions, resulting in us rejecting valid code.
This also significantly improves performance for `deque` in some cases.
2026-01-09 12:06:43 +01:00
Nikolas Klauser
9a8421fa61
[libc++] Update our release notes for the upcoming release ( #174625 )
2026-01-08 13:26:04 +01:00
Nikolas Klauser
06c6a5020f
[libc++] Optimize search_n ( #171389 )
...
This changes the algorithm to more efficiently skip ranges which cannot
match the needle for random access iterators. Specifically, we now
search for a mismatching element from the back of the subrange we want
to check. When a mismatch occurs we can directly start one after the
mismatched element, since there cannot possibly be a matching subrange
starting between the start of the subrange we checked and the mismatched
element (since all elements have to be equal). The algorithm also
remembers the subrange which was already match as being equal and
doesn't try to compare it a second time, reducing the time spent in case
of a match.
```
Benchmark old new Difference % Difference
--------------------------------------------------- -------------- -------------- ------------ --------------
rng::search_n(deque<int>)_(no_match)/1000 458.33 14.22 -444.11 -96.90%
rng::search_n(deque<int>)_(no_match)/1024 456.17 13.89 -442.28 -96.95%
rng::search_n(deque<int>)_(no_match)/1048576 453420.38 17.69 -453402.69 -100.00%
rng::search_n(deque<int>)_(no_match)/8192 3566.08 17.60 -3548.49 -99.51%
rng::search_n(deque<int>,_pred)_(no_match)/1000 597.88 15.25 -582.63 -97.45%
rng::search_n(deque<int>,_pred)_(no_match)/1024 608.42 15.39 -593.03 -97.47%
rng::search_n(deque<int>,_pred)_(no_match)/1048576 594533.99 18.91 -594515.08 -100.00%
rng::search_n(deque<int>,_pred)_(no_match)/8192 4670.23 18.88 -4651.35 -99.60%
rng::search_n(list<int>)_(no_match)/1000 733.72 730.22 -3.50 -0.48%
rng::search_n(list<int>)_(no_match)/1024 759.93 753.10 -6.84 -0.90%
rng::search_n(list<int>)_(no_match)/1048576 833841.54 813483.75 -20357.79 -2.44%
rng::search_n(list<int>)_(no_match)/8192 8352.18 8417.31 65.14 0.78%
rng::search_n(list<int>,_pred)_(no_match)/1000 776.79 789.72 12.93 1.66%
rng::search_n(list<int>,_pred)_(no_match)/1024 788.42 806.70 18.28 2.32%
rng::search_n(list<int>,_pred)_(no_match)/1048576 955536.40 982976.81 27440.41 2.87%
rng::search_n(list<int>,_pred)_(no_match)/8192 8874.02 8915.18 41.16 0.46%
rng::search_n(vector<int>)_(no_match)/1000 212.69 3.79 -208.90 -98.22%
rng::search_n(vector<int>)_(no_match)/1024 219.67 3.70 -215.96 -98.31%
rng::search_n(vector<int>)_(no_match)/1048576 209622.54 3.67 -209618.87 -100.00%
rng::search_n(vector<int>)_(no_match)/8192 1643.80 3.83 -1639.98 -99.77%
rng::search_n(vector<int>,_pred)_(no_match)/1000 461.93 7.55 -454.38 -98.36%
rng::search_n(vector<int>,_pred)_(no_match)/1024 472.43 7.74 -464.69 -98.36%
rng::search_n(vector<int>,_pred)_(no_match)/1048576 546180.29 8.71 -546171.58 -100.00%
rng::search_n(vector<int>,_pred)_(no_match)/8192 3786.26 7.88 -3778.38 -99.79%
std::search_n(deque<int>)_(no_match)/1000 455.53 14.19 -441.34 -96.88%
std::search_n(deque<int>)_(no_match)/1024 459.79 13.98 -445.81 -96.96%
std::search_n(deque<int>)_(no_match)/1048576 449780.32 17.99 -449762.33 -100.00%
std::search_n(deque<int>)_(no_match)/8192 3508.55 17.97 -3490.58 -99.49%
std::search_n(deque<int>,_pred)_(no_match)/1000 571.53 17.16 -554.37 -97.00%
std::search_n(deque<int>,_pred)_(no_match)/1024 584.43 17.09 -567.34 -97.08%
std::search_n(deque<int>,_pred)_(no_match)/1048576 581418.31 19.16 -581399.15 -100.00%
std::search_n(deque<int>,_pred)_(no_match)/8192 4661.97 19.36 -4642.61 -99.58%
std::search_n(list<int>)_(no_match)/1000 722.45 710.39 -12.06 -1.67%
std::search_n(list<int>)_(no_match)/1024 748.50 727.08 -21.42 -2.86%
std::search_n(list<int>)_(no_match)/1048576 821655.28 784520.12 -37135.16 -4.52%
std::search_n(list<int>)_(no_match)/8192 7941.73 8002.05 60.32 0.76%
std::search_n(list<int>,_pred)_(no_match)/1000 766.59 786.31 19.72 2.57%
std::search_n(list<int>,_pred)_(no_match)/1024 785.92 804.43 18.51 2.35%
std::search_n(list<int>,_pred)_(no_match)/1048576 948252.76 969125.41 20872.65 2.20%
std::search_n(list<int>,_pred)_(no_match)/8192 8658.99 8825.71 166.72 1.93%
std::search_n(vector<int>)_(no_match)/1000 210.36 3.47 -206.89 -98.35%
std::search_n(vector<int>)_(no_match)/1024 217.60 4.13 -213.47 -98.10%
std::search_n(vector<int>)_(no_match)/1048576 209386.43 3.51 -209382.92 -100.00%
std::search_n(vector<int>)_(no_match)/8192 1643.79 3.50 -1640.29 -99.79%
std::search_n(vector<int>,_pred)_(no_match)/1000 460.88 5.44 -455.45 -98.82%
std::search_n(vector<int>,_pred)_(no_match)/1024 475.36 5.43 -469.93 -98.86%
std::search_n(vector<int>,_pred)_(no_match)/1048576 682722.75 7.15 -682715.60 -100.00%
std::search_n(vector<int>,_pred)_(no_match)/8192 3779.95 5.43 -3774.52 -99.86%
Geomean 4956.15 87.96 -4868.19 -98.23%
```
Fixes #129327
2026-01-08 11:26:08 +01:00
Rafail Shakhin ogly
ec7b63771c
[libc++][chrono] P2592R3: Hashing for chrono ( #165132 )
2026-01-03 10:32:14 +08:00
Matthias Wippich
617b446176
[libc++] Implement P1789R3: Library Support for Expansion Statements ( #167184 )
...
[P1789R3](https://isocpp.org/files/papers/P1789R3.pdf ) was accepted for
C++26 through LWG motion 14 at the 2025 Kona meeting. This patch
implements it, along with tests and documentation changes.
Closes #167268
---------
Co-authored-by: Tsche <che@pydong.org>
2025-12-26 09:07:13 +08:00
Hristo Hristov
94c014a5fd
[libc++][NFC] Fixed formatting in Release Notes ( #173526 )
2025-12-25 11:37:00 +02:00
William Tran-Viet
4c9d1bdf94
[libc++] Implement P3836R2: Make optional<T&> trivially copyable ( #171528 )
...
Resolves #171275
- `*_assign_base` base class trivial overloads needed to be updated to
allow references.
- Add tests
- Update release notes
2025-12-24 15:44:32 +08:00
Nikolas Klauser
79a88949cd
[libc++] Optimize rotate ( #120890 )
...
This implements a new algorithm for `rotate` with random access
iterators, which uses `swap_ranges`. This reduces cache misses and
allows for vectorization.
Apple M4:
```
Benchmark old new Difference % Difference
--------------------------------------------------- -------------- -------------- ------------ --------------
rng::rotate(deque<int>)_(1_element_backward)/1024 46.17 45.13 -1.04 -2.26%
rng::rotate(deque<int>)_(1_element_backward)/32 4.90 4.92 0.02 0.45%
rng::rotate(deque<int>)_(1_element_backward)/50 6.12 6.02 -0.10 -1.56%
rng::rotate(deque<int>)_(1_element_backward)/8192 329.97 330.49 0.52 0.16%
rng::rotate(deque<int>)_(1_element_forward)/1024 42.20 42.99 0.79 1.87%
rng::rotate(deque<int>)_(1_element_forward)/32 4.99 5.26 0.27 5.37%
rng::rotate(deque<int>)_(1_element_forward)/50 6.33 6.48 0.14 2.28%
rng::rotate(deque<int>)_(1_element_forward)/8192 317.40 318.68 1.28 0.40%
rng::rotate(deque<int>)_(by_1/2)/1024 185.42 184.23 -1.18 -0.64%
rng::rotate(deque<int>)_(by_1/2)/32 8.72 8.99 0.27 3.14%
rng::rotate(deque<int>)_(by_1/2)/50 12.03 11.60 -0.43 -3.59%
rng::rotate(deque<int>)_(by_1/2)/8192 1549.94 1549.30 -0.64 -0.04%
rng::rotate(deque<int>)_(by_1/3)/1024 1886.50 409.41 -1477.09 -78.30%
rng::rotate(deque<int>)_(by_1/3)/32 46.51 21.68 -24.84 -53.40%
rng::rotate(deque<int>)_(by_1/3)/50 77.70 29.85 -47.85 -61.58%
rng::rotate(deque<int>)_(by_1/3)/8192 22814.91 3171.92 -19642.99 -86.10%
rng::rotate(deque<int>)_(by_1/4)/1024 811.39 283.28 -528.11 -65.09%
rng::rotate(deque<int>)_(by_1/4)/32 30.30 14.44 -15.86 -52.35%
rng::rotate(deque<int>)_(by_1/4)/50 76.23 29.29 -46.94 -61.58%
rng::rotate(deque<int>)_(by_1/4)/8192 7154.50 2357.48 -4797.02 -67.05%
rng::rotate(list<int>)_(1_element_backward)/1024 1483.46 742.31 -741.15 -49.96%
rng::rotate(list<int>)_(1_element_backward)/32 16.17 16.37 0.20 1.24%
rng::rotate(list<int>)_(1_element_backward)/50 29.31 29.20 -0.10 -0.34%
rng::rotate(list<int>)_(1_element_backward)/8192 8896.07 8949.56 53.49 0.60%
rng::rotate(list<int>)_(1_element_forward)/1024 1481.36 742.24 -739.12 -49.89%
rng::rotate(list<int>)_(1_element_forward)/32 15.72 16.22 0.50 3.19%
rng::rotate(list<int>)_(1_element_forward)/50 28.91 28.87 -0.03 -0.12%
rng::rotate(list<int>)_(1_element_forward)/8192 9595.63 9846.80 251.16 2.62%
rng::rotate(list<int>)_(by_1/2)/1024 833.67 408.22 -425.46 -51.03%
rng::rotate(list<int>)_(by_1/2)/32 8.88 8.76 -0.11 -1.25%
rng::rotate(list<int>)_(by_1/2)/50 15.67 15.73 0.06 0.40%
rng::rotate(list<int>)_(by_1/2)/8192 6392.01 6597.30 205.30 3.21%
rng::rotate(list<int>)_(by_1/3)/1024 1360.66 872.00 -488.66 -35.91%
rng::rotate(list<int>)_(by_1/3)/32 19.72 19.37 -0.35 -1.80%
rng::rotate(list<int>)_(by_1/3)/50 33.15 33.12 -0.04 -0.12%
rng::rotate(list<int>)_(by_1/3)/8192 10807.14 11216.71 409.58 3.79%
rng::rotate(list<int>)_(by_1/4)/1024 624.92 625.80 0.88 0.14%
rng::rotate(list<int>)_(by_1/4)/32 15.28 15.37 0.09 0.60%
rng::rotate(list<int>)_(by_1/4)/50 32.27 32.78 0.52 1.60%
rng::rotate(list<int>)_(by_1/4)/8192 11266.66 9594.79 -1671.87 -14.84%
rng::rotate(vector<bool>)_(1_element_backward)/1024 32.10 31.94 -0.16 -0.51%
rng::rotate(vector<bool>)_(1_element_backward)/32 18.48 18.07 -0.41 -2.21%
rng::rotate(vector<bool>)_(1_element_backward)/50 18.49 18.19 -0.30 -1.64%
rng::rotate(vector<bool>)_(1_element_backward)/8192 113.76 112.91 -0.85 -0.75%
rng::rotate(vector<bool>)_(1_element_forward)/1024 30.87 30.72 -0.15 -0.48%
rng::rotate(vector<bool>)_(1_element_forward)/32 18.16 17.98 -0.18 -1.01%
rng::rotate(vector<bool>)_(1_element_forward)/50 17.98 17.98 0.01 0.03%
rng::rotate(vector<bool>)_(1_element_forward)/8192 111.84 111.50 -0.34 -0.31%
rng::rotate(vector<bool>)_(by_1/2)/1024 9.27 9.34 0.07 0.75%
rng::rotate(vector<bool>)_(by_1/2)/32 18.32 17.90 -0.42 -2.29%
rng::rotate(vector<bool>)_(by_1/2)/50 18.14 17.69 -0.45 -2.49%
rng::rotate(vector<bool>)_(by_1/2)/8192 16.23 16.80 0.57 3.49%
rng::rotate(vector<bool>)_(by_1/3)/1024 58.89 58.74 -0.15 -0.25%
rng::rotate(vector<bool>)_(by_1/3)/32 18.16 17.74 -0.41 -2.28%
rng::rotate(vector<bool>)_(by_1/3)/50 18.15 17.72 -0.43 -2.38%
rng::rotate(vector<bool>)_(by_1/3)/8192 164.52 166.17 1.65 1.00%
rng::rotate(vector<bool>)_(by_1/4)/1024 13.44 14.20 0.76 5.65%
rng::rotate(vector<bool>)_(by_1/4)/32 18.38 17.86 -0.52 -2.84%
rng::rotate(vector<bool>)_(by_1/4)/50 18.26 17.75 -0.51 -2.79%
rng::rotate(vector<bool>)_(by_1/4)/8192 34.49 34.59 0.11 0.31%
rng::rotate(vector<int>)_(1_element_backward)/1024 37.22 37.55 0.33 0.88%
rng::rotate(vector<int>)_(1_element_backward)/32 3.02 3.01 -0.00 -0.10%
rng::rotate(vector<int>)_(1_element_backward)/50 5.31 5.33 0.02 0.31%
rng::rotate(vector<int>)_(1_element_backward)/8192 302.96 295.02 -7.94 -2.62%
rng::rotate(vector<int>)_(1_element_forward)/1024 36.78 36.97 0.19 0.51%
rng::rotate(vector<int>)_(1_element_forward)/32 3.08 3.19 0.11 3.56%
rng::rotate(vector<int>)_(1_element_forward)/50 5.33 5.33 -0.00 -0.05%
rng::rotate(vector<int>)_(1_element_forward)/8192 288.25 285.28 -2.97 -1.03%
rng::rotate(vector<int>)_(by_1/2)/1024 32.49 32.13 -0.36 -1.10%
rng::rotate(vector<int>)_(by_1/2)/32 3.80 2.63 -1.17 -30.82%
rng::rotate(vector<int>)_(by_1/2)/50 5.29 3.69 -1.59 -30.13%
rng::rotate(vector<int>)_(by_1/2)/8192 256.13 252.05 -4.07 -1.59%
rng::rotate(vector<int>)_(by_1/3)/1024 1389.57 135.85 -1253.72 -90.22%
rng::rotate(vector<int>)_(by_1/3)/32 21.73 11.99 -9.73 -44.80%
rng::rotate(vector<int>)_(by_1/3)/50 40.23 11.88 -28.35 -70.48%
rng::rotate(vector<int>)_(by_1/3)/8192 11040.23 946.51 -10093.72 -91.43%
rng::rotate(vector<int>)_(by_1/4)/1024 335.13 49.05 -286.08 -85.36%
rng::rotate(vector<int>)_(by_1/4)/32 12.32 6.06 -6.26 -50.83%
rng::rotate(vector<int>)_(by_1/4)/50 40.54 12.54 -28.00 -69.07%
rng::rotate(vector<int>)_(by_1/4)/8192 2648.84 391.91 -2256.93 -85.20%
std::rotate(deque<int>)_(1_element_backward)/1024 45.81 45.88 0.08 0.16%
std::rotate(deque<int>)_(1_element_backward)/32 4.81 4.85 0.04 0.76%
std::rotate(deque<int>)_(1_element_backward)/50 6.11 6.10 -0.01 -0.13%
std::rotate(deque<int>)_(1_element_backward)/8192 329.99 330.63 0.64 0.19%
std::rotate(deque<int>)_(1_element_forward)/1024 42.45 42.21 -0.24 -0.57%
std::rotate(deque<int>)_(1_element_forward)/32 5.03 5.14 0.11 2.23%
std::rotate(deque<int>)_(1_element_forward)/50 5.96 6.04 0.09 1.43%
std::rotate(deque<int>)_(1_element_forward)/8192 316.09 317.73 1.64 0.52%
std::rotate(deque<int>)_(by_1/2)/1024 185.34 185.41 0.07 0.04%
std::rotate(deque<int>)_(by_1/2)/32 8.08 8.57 0.49 6.01%
std::rotate(deque<int>)_(by_1/2)/50 11.13 11.61 0.48 4.35%
std::rotate(deque<int>)_(by_1/2)/8192 1549.74 1527.97 -21.77 -1.40%
std::rotate(deque<int>)_(by_1/3)/1024 1837.15 410.26 -1426.89 -77.67%
std::rotate(deque<int>)_(by_1/3)/32 46.73 22.85 -23.88 -51.11%
std::rotate(deque<int>)_(by_1/3)/50 78.05 29.61 -48.43 -62.06%
std::rotate(deque<int>)_(by_1/3)/8192 22784.08 3174.02 -19610.06 -86.07%
std::rotate(deque<int>)_(by_1/4)/1024 874.13 282.91 -591.22 -67.64%
std::rotate(deque<int>)_(by_1/4)/32 31.14 14.31 -16.83 -54.05%
std::rotate(deque<int>)_(by_1/4)/50 77.39 28.67 -48.72 -62.96%
std::rotate(deque<int>)_(by_1/4)/8192 7207.73 2344.73 -4863.00 -67.47%
std::rotate(list<int>)_(1_element_backward)/1024 1490.45 745.80 -744.65 -49.96%
std::rotate(list<int>)_(1_element_backward)/32 16.15 16.43 0.28 1.71%
std::rotate(list<int>)_(1_element_backward)/50 29.28 29.29 0.01 0.02%
std::rotate(list<int>)_(1_element_backward)/8192 9305.23 10372.35 1067.13 11.47%
std::rotate(list<int>)_(1_element_forward)/1024 1479.13 743.71 -735.42 -49.72%
std::rotate(list<int>)_(1_element_forward)/32 15.86 16.21 0.35 2.20%
std::rotate(list<int>)_(1_element_forward)/50 28.91 28.90 -0.01 -0.04%
std::rotate(list<int>)_(1_element_forward)/8192 9796.34 8826.58 -969.76 -9.90%
std::rotate(list<int>)_(by_1/2)/1024 851.06 411.44 -439.61 -51.66%
std::rotate(list<int>)_(by_1/2)/32 8.90 8.80 -0.10 -1.10%
std::rotate(list<int>)_(by_1/2)/50 15.69 15.69 0.00 0.02%
std::rotate(list<int>)_(by_1/2)/8192 6479.34 6599.58 120.24 1.86%
std::rotate(list<int>)_(by_1/3)/1024 865.82 877.81 11.99 1.38%
std::rotate(list<int>)_(by_1/3)/32 19.52 19.44 -0.09 -0.44%
std::rotate(list<int>)_(by_1/3)/50 33.67 33.14 -0.53 -1.59%
std::rotate(list<int>)_(by_1/3)/8192 10513.57 10355.02 -158.55 -1.51%
std::rotate(list<int>)_(by_1/4)/1024 639.35 655.30 15.95 2.49%
std::rotate(list<int>)_(by_1/4)/32 15.22 15.45 0.24 1.55%
std::rotate(list<int>)_(by_1/4)/50 32.51 32.93 0.42 1.29%
std::rotate(list<int>)_(by_1/4)/8192 9883.06 9284.28 -598.79 -6.06%
std::rotate(vector<bool>)_(1_element_backward)/1024 30.77 30.95 0.18 0.58%
std::rotate(vector<bool>)_(1_element_backward)/32 17.73 17.57 -0.16 -0.89%
std::rotate(vector<bool>)_(1_element_backward)/50 17.74 17.58 -0.16 -0.91%
std::rotate(vector<bool>)_(1_element_backward)/8192 111.37 111.04 -0.33 -0.29%
std::rotate(vector<bool>)_(1_element_forward)/1024 30.16 29.92 -0.24 -0.81%
std::rotate(vector<bool>)_(1_element_forward)/32 17.22 17.38 0.16 0.94%
std::rotate(vector<bool>)_(1_element_forward)/50 17.22 17.36 0.14 0.83%
std::rotate(vector<bool>)_(1_element_forward)/8192 111.28 111.19 -0.09 -0.08%
std::rotate(vector<bool>)_(by_1/2)/1024 9.20 9.65 0.46 4.96%
std::rotate(vector<bool>)_(by_1/2)/32 17.23 17.12 -0.11 -0.62%
std::rotate(vector<bool>)_(by_1/2)/50 17.18 17.04 -0.14 -0.82%
std::rotate(vector<bool>)_(by_1/2)/8192 15.93 16.92 0.99 6.22%
std::rotate(vector<bool>)_(by_1/3)/1024 57.99 58.05 0.06 0.10%
std::rotate(vector<bool>)_(by_1/3)/32 17.14 17.06 -0.08 -0.47%
std::rotate(vector<bool>)_(by_1/3)/50 17.09 16.95 -0.15 -0.87%
std::rotate(vector<bool>)_(by_1/3)/8192 164.14 165.70 1.56 0.95%
std::rotate(vector<bool>)_(by_1/4)/1024 14.00 14.21 0.21 1.49%
std::rotate(vector<bool>)_(by_1/4)/32 17.20 17.20 -0.00 -0.00%
std::rotate(vector<bool>)_(by_1/4)/50 17.09 17.10 0.01 0.08%
std::rotate(vector<bool>)_(by_1/4)/8192 33.90 34.16 0.26 0.76%
std::rotate(vector<int>)_(1_element_backward)/1024 37.04 37.54 0.50 1.35%
std::rotate(vector<int>)_(1_element_backward)/32 3.01 3.01 0.00 0.04%
std::rotate(vector<int>)_(1_element_backward)/50 5.30 4.96 -0.34 -6.44%
std::rotate(vector<int>)_(1_element_backward)/8192 302.63 286.92 -15.71 -5.19%
std::rotate(vector<int>)_(1_element_forward)/1024 36.83 36.88 0.05 0.15%
std::rotate(vector<int>)_(1_element_forward)/32 3.08 3.06 -0.02 -0.56%
std::rotate(vector<int>)_(1_element_forward)/50 5.34 5.07 -0.26 -4.95%
std::rotate(vector<int>)_(1_element_forward)/8192 283.85 284.99 1.14 0.40%
std::rotate(vector<int>)_(by_1/2)/1024 32.12 32.19 0.06 0.20%
std::rotate(vector<int>)_(by_1/2)/32 3.83 2.22 -1.61 -42.16%
std::rotate(vector<int>)_(by_1/2)/50 4.28 4.38 0.09 2.19%
std::rotate(vector<int>)_(by_1/2)/8192 256.28 252.63 -3.65 -1.42%
std::rotate(vector<int>)_(by_1/3)/1024 1386.79 142.76 -1244.03 -89.71%
std::rotate(vector<int>)_(by_1/3)/32 21.76 11.54 -10.22 -46.98%
std::rotate(vector<int>)_(by_1/3)/50 40.30 11.79 -28.51 -70.74%
std::rotate(vector<int>)_(by_1/3)/8192 11017.09 949.95 -10067.14 -91.38%
std::rotate(vector<int>)_(by_1/4)/1024 335.51 48.69 -286.83 -85.49%
std::rotate(vector<int>)_(by_1/4)/32 12.31 6.09 -6.22 -50.51%
std::rotate(vector<int>)_(by_1/4)/50 40.82 13.03 -27.79 -68.07%
std::rotate(vector<int>)_(by_1/4)/8192 2647.90 392.58 -2255.32 -85.17%
Geomean 76.74 56.58 -20.16 -26.27%
```
Fixes #54949
2025-12-23 10:18:43 +01:00
Hui
fc4661aa11
[libc++] Implement adjacent_transform ( #168208 )
...
This patch implements std::ranges::adjacent_transform_view. This is part
of P2321R2 tracked
by #105169 .
2025-12-21 09:08:09 +00:00
Hui
cd13170aea
[libc++] Implement P3567R2 flat_meow fixes ( #162022 )
...
Fixes #171272
---------
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2025-12-20 21:18:44 +00:00
Janet Cobb
ef190061d3
[libc++][concepts] P2404R3: Move-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with ( #99420 )
...
This implements all of [P2404R3](https://wg21.link/p2404r3 )'s concept
changes.
---------
Co-authored-by: A. Jiang <de34@live.cn>
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2025-12-19 17:56:32 +08:00
saipubw
1c06165c9b
[libc++] Make std::align an inline function ( #167472 )
...
`std::align` is heavily used in memory allocators. When we attempted to
switch from libstdc++ to libc++, we observed a **50%** performance
regression in a database query bench: the issue is that `std::align` in
libc++ is not an inline function, which prevents the compiler from
performing inlining optimizations.
make `std::align` an inline function will run about 2x faster. See
[benchmark
result](https://quick-bench.com/q/wPTnt9JCGn2S-3bu5gY9YrEf6KU ).
---------
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2025-12-18 17:55:28 +08:00
Hui
1e15dbe311
[libc++] Implement adjacent_view ( #165089 )
2025-12-13 19:33:32 +00:00
Nikolas Klauser
a34a92d9e2
[libc++] Always return bool from bitset::operator[](size_t) const ( #169894 )
...
This takes an ABI break unconditionally, since it's small enough that
nobody should be affected. This both simplifies `bitset` a bit and makes
us more conforming.
2025-12-12 09:06:50 +01:00
Nikolas Klauser
4fc5b6d8c4
[libc++] Optimize {std,ranges}::for_each for iterating over __trees ( #164405 )
...
This patch optimizes how `for_each` iterates over trees by using
recursion and storing pointers to the next nodes on the stack. This
avoids pointer chasing through the `__parent_` pointer, reducing cache
misses. It also makes use of the compiler being able tail-call optimize
the recursive function, removing back-tracking the iterators have to do.
```
Benchmark old new Difference % Difference
-------------------------------------------------- -------------- -------------- ------------ --------------
rng::for_each(map<int>)/32 35.19 26.67 -8.52 -24.21%
rng::for_each(map<int>)/50 64.13 40.68 -23.45 -36.57%
rng::for_each(map<int>)/8 5.06 6.49 1.43 28.21%
rng::for_each(map<int>)/8192 22893.89 9266.68 -13627.21 -59.52%
rng::for_each(map<int>::iterator)/32 35.51 26.88 -8.63 -24.31%
rng::for_each(map<int>::iterator)/50 64.39 41.24 -23.15 -35.95%
rng::for_each(map<int>::iterator)/8 5.12 5.93 0.81 15.80%
rng::for_each(map<int>::iterator)/8192 21283.14 9736.83 -11546.31 -54.25%
rng::for_each(multimap<int>)/32 35.22 26.61 -8.61 -24.45%
rng::for_each(multimap<int>)/50 64.10 40.07 -24.03 -37.49%
rng::for_each(multimap<int>)/8 5.08 6.69 1.61 31.70%
rng::for_each(multimap<int>)/8192 23130.44 9026.16 -14104.28 -60.98%
rng::for_each(multimap<int>::iterator)/32 35.40 25.08 -10.32 -29.15%
rng::for_each(multimap<int>::iterator)/50 64.19 38.15 -26.04 -40.56%
rng::for_each(multimap<int>::iterator)/8 5.04 5.25 0.22 4.31%
rng::for_each(multimap<int>::iterator)/8192 22875.97 9392.08 -13483.89 -58.94%
rng::for_each(multiset<int>)/32 35.82 27.11 -8.72 -24.33%
rng::for_each(multiset<int>)/50 62.92 41.59 -21.32 -33.89%
rng::for_each(multiset<int>)/8 4.79 6.79 2.00 41.70%
rng::for_each(multiset<int>)/8192 22642.68 9280.95 -13361.73 -59.01%
rng::for_each(multiset<int>::iterator)/32 35.76 26.71 -9.04 -25.28%
rng::for_each(multiset<int>::iterator)/50 63.44 39.00 -24.44 -38.53%
rng::for_each(multiset<int>::iterator)/8 4.90 5.21 0.30 6.18%
rng::for_each(multiset<int>::iterator)/8192 19930.45 9867.60 -10062.85 -50.49%
rng::for_each(set<int>)/32 35.90 27.30 -8.60 -23.96%
rng::for_each(set<int>)/50 63.15 40.75 -22.40 -35.47%
rng::for_each(set<int>)/8 4.77 6.83 2.06 43.23%
rng::for_each(set<int>)/8192 20262.77 9381.57 -10881.20 -53.70%
rng::for_each(set<int>::iterator)/32 36.02 26.42 -9.60 -26.64%
rng::for_each(set<int>::iterator)/50 63.29 37.97 -25.32 -40.01%
rng::for_each(set<int>::iterator)/8 4.72 5.22 0.50 10.50%
rng::for_each(set<int>::iterator)/8192 20041.91 9831.91 -10210.00 -50.94%
```
2025-12-12 09:05:51 +01:00
Nikolas Klauser
df6c27e752
[libc++] Make std::allocator always trivially default constructible ( #169914 )
...
This is technically ABI breaking, since `is_trivial` and
`is_trivially_default_constructible` now return different results.
However, I don't think that's a significant issue, since `allocator` is
almost always used in classes which own memory, making them non-trivial
anyways.
2025-12-11 10:27:43 +01:00
Nikolas Klauser
c567e28a9d
[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%
```
2025-12-10 10:18:59 +01:00
Hui
73a13839d3
[libc++] Allows any types of size 4 and 8 to use native platform ulock_wait ( #161086 )
...
This is to address #146145
The issue before was that, for `std::atomic::wait/notify`, we only
support `uint64_t` to go through the native `ulock_wait` directly. Any
other types will go through the global contention table's `atomic`,
increasing the chances of spurious wakeup. This PR tries to allow any
types that are of size 4 or 8 to directly go to the `ulock_wait`.
This PR is just proof of concept. If we like this idea, I can go further
to update the Linux/FreeBSD branch and add ABI macros so the existing
behaviours are reserved under the stable ABI
Here are some benchmark results
```
Benchmark Time CPU Time Old Time New CPU Old CPU New
----------------------------------------------------------------------------------------------------------------------------------------------------
BM_stop_token_single_thread_reg_unreg_callback/1024 -0.1113 -0.1165 51519 45785 51397 45408
BM_stop_token_single_thread_reg_unreg_callback/4096 -0.2727 -0.1447 249685 181608 211865 181203
BM_stop_token_single_thread_reg_unreg_callback/65536 -0.1241 -0.1237 3308930 2898396 3300986 2892608
BM_stop_token_single_thread_reg_unreg_callback/262144 +0.0335 -0.1920 13237682 13681632 13208849 10673254
OVERALL_GEOMEAN -0.1254 -0.1447 0 0 0 0
```
```
Benchmark Time CPU Time Old Time New CPU Old CPU New
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
BM_1_atomic_1_waiter_1_notifier<KeepNotifying, NumHighPrioTasks<0>>/65536 -0.3344 -0.2424 5960741 3967212 5232250 3964085
BM_1_atomic_1_waiter_1_notifier<KeepNotifying, NumHighPrioTasks<0>>/131072 -0.1474 -0.1475 9144356 7796745 9137547 7790193
BM_1_atomic_1_waiter_1_notifier<KeepNotifying, NumHighPrioTasks<0>>/262144 -0.1336 -0.1340 18333441 15883805 18323711 15868500
OVERALL_GEOMEAN -0.2107 -0.1761 0 0 0 0
```
```
Benchmark Time CPU Time Old Time New CPU Old CPU New
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
BM_1_atomic_multi_waiter_1_notifier<KeepNotifying, NumWaitingThreads<2>, NumHighPrioTasks<0>>/16384 +0.2321 -0.0081 836618 1030772 833197 826476
BM_1_atomic_multi_waiter_1_notifier<KeepNotifying, NumWaitingThreads<2>, NumHighPrioTasks<0>>/32768 -0.3034 -0.1329 2182721 1520569 1747211 1515028
BM_1_atomic_multi_waiter_1_notifier<KeepNotifying, NumWaitingThreads<2>, NumHighPrioTasks<0>>/65536 -0.0924 -0.0924 3389098 3075897 3378486 3066448
BM_1_atomic_multi_waiter_1_notifier<KeepNotifying, NumWaitingThreads<8>, NumHighPrioTasks<0>>/4096 +0.0464 +0.0474 664233 695080 657736 688892
BM_1_atomic_multi_waiter_1_notifier<KeepNotifying, NumWaitingThreads<8>, NumHighPrioTasks<0>>/8192 -0.0279 -0.0267 1336041 1298794 1324270 1288953
BM_1_atomic_multi_waiter_1_notifier<KeepNotifying, NumWaitingThreads<8>, NumHighPrioTasks<0>>/16384 +0.0270 +0.0304 2543004 2611786 2517471 2593975
BM_1_atomic_multi_waiter_1_notifier<KeepNotifying, NumWaitingThreads<32>, NumHighPrioTasks<0>>/1024 +0.0423 +0.0941 473621 493657 325604 356245
BM_1_atomic_multi_waiter_1_notifier<KeepNotifying, NumWaitingThreads<32>, NumHighPrioTasks<0>>/2048 +0.0420 +0.0675 906266 944349 636253 679169
BM_1_atomic_multi_waiter_1_notifier<KeepNotifying, NumWaitingThreads<32>, NumHighPrioTasks<0>>/4096 +0.0359 +0.0378 1761584 1824783 1015092 1053439
OVERALL_GEOMEAN -0.0097 -0.0007 0 0 0 0
```
```
Benchmark Time CPU Time Old Time New CPU Old CPU New
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
BM_N_atomics_N_waiter_N_notifier<KeepNotifying, NumberOfAtomics<2>, NumHighPrioTasks<0>>/4096 -0.0990 -0.1001 371100 334370 369984 332955
BM_N_atomics_N_waiter_N_notifier<KeepNotifying, NumberOfAtomics<2>, NumHighPrioTasks<0>>/8192 -0.0305 -0.0314 698228 676908 696418 674585
BM_N_atomics_N_waiter_N_notifier<KeepNotifying, NumberOfAtomics<2>, NumHighPrioTasks<0>>/16384 -0.0258 -0.0268 1383530 1347894 1380665 1343680
BM_N_atomics_N_waiter_N_notifier<KeepNotifying, NumberOfAtomics<8>, NumHighPrioTasks<0>>/1024 +0.0465 +0.4702 937821 981388 472087 694082
BM_N_atomics_N_waiter_N_notifier<KeepNotifying, NumberOfAtomics<8>, NumHighPrioTasks<0>>/2048 +0.1596 +0.9140 1704819 1976899 616419 1179852
BM_N_atomics_N_waiter_N_notifier<KeepNotifying, NumberOfAtomics<8>, NumHighPrioTasks<0>>/4096 -0.1018 -0.2316 3793976 3407609 1912209 1469331
BM_N_atomics_N_waiter_N_notifier<KeepNotifying, NumberOfAtomics<32>, NumHighPrioTasks<0>>/256 +0.0395 +0.5818 30102662 31292982 174650 276270
BM_N_atomics_N_waiter_N_notifier<KeepNotifying, NumberOfAtomics<32>, NumHighPrioTasks<0>>/512 -0.0065 +1.2860 33079634 32863968 162150 370680
BM_N_atomics_N_waiter_N_notifier<KeepNotifying, NumberOfAtomics<32>, NumHighPrioTasks<0>>/1024 -0.0325 +0.4683 36581740 35392385 282320 414520
OVERALL_GEOMEAN -0.0084 +0.2878 0 0 0 0
```
---------
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2025-12-07 12:04:11 +00:00
Nikolas Klauser
2bdd1357c8
[libc++] Optimize num_get integral functions ( #121795 )
...
```
---------------------------------------------------
Benchmark old new
---------------------------------------------------
BM_num_get<bool> 86.5 ns 32.3 ns
BM_num_get<long> 82.1 ns 30.3 ns
BM_num_get<long long> 85.2 ns 33.4 ns
BM_num_get<unsigned short> 85.3 ns 31.2 ns
BM_num_get<unsigned int> 84.2 ns 31.1 ns
BM_num_get<unsigned long> 83.6 ns 31.9 ns
BM_num_get<unsigned long long> 87.7 ns 31.5 ns
BM_num_get<float> 116 ns 114 ns
BM_num_get<double> 114 ns 114 ns
BM_num_get<long double> 113 ns 114 ns
BM_num_get<void*> 151 ns 144 ns
```
This patch applies multiple optimizations:
- Stages two and three of do_get are merged and a custom integer parser
has been implemented
This avoids allocations, removes the need for strto{,u}ll and avoids
__stage2_int_loop (avoiding extra writes to memory)
- std::find has been replaced with __atoms_offset, which uses vector
instructions to look for a character
Fixes #158100
Fixes #158102
2025-11-24 16:53:58 +01:00
Jordan Rupprecht
347512ff38
[libc++] Revert fstream::read optimizations ( #168894 )
...
This causes various runtime failures, as reported in #168628 .
This reverts both #165223 and #167779
2025-11-21 07:08:15 -06:00
Nikolas Klauser
ad31e11ab6
[libc++] Make views::iota aware of __int128 ( #167869 )
...
Fixes #167991
2025-11-19 15:19:54 +01:00
William Tran-Viet
389a23c538
[libc++] Implement P2988R12: std::optional<T&> ( #155202 )
...
Resolves #148131
- Unlock `std::optional<T&>` implementation
- Allow instantiations of `optional<T(&)(...)>` and `optional<T(&)[]>`
but disables `value_or()` and `optional::iterator` + all `iterator`
related functions
- Update documentation
- Update tests
2025-11-12 11:00:08 +08:00
Nikolas Klauser
9b114c5d9a
[libc++] Optimize fstream::read ( #165223 )
...
```
Benchmark old new Difference % Difference
----------- -------- -------- ------------ --------------
bm_read 2468.45 736.27 -1732.18 -70.17%
```
2025-11-07 10:31:31 +00:00
A. Jiang
bfcd67c347
[libc++][docs] Update status for P2641R4 ( #166073 )
...
Follows-up 2527b071ba2e39fdd62eeb73b89318468595c316 which missed
updating the status in the documentations.
2025-11-03 11:59:10 +08:00
Connector Switch
0621fd0b88
[libcxx] Optimize rng::generate_n for segmented iterators ( #165280 )
...
Part of #102817 .
This patch optimizes `rng::generate_n` for segmented iterators by
forwarding the implementation directly to `std::generate_n`.
- before
```
rng::generate_n(deque<int>)/32 21.7 ns 22.0 ns 32000000
rng::generate_n(deque<int>)/50 30.8 ns 30.7 ns 22400000
rng::generate_n(deque<int>)/1024 492 ns 488 ns 1120000
rng::generate_n(deque<int>)/8192 3938 ns 3924 ns 179200
```
- after
```
rng::generate_n(deque<int>)/32 11.0 ns 11.0 ns 64000000
rng::generate_n(deque<int>)/50 16.2 ns 16.1 ns 40727273
rng::generate_n(deque<int>)/1024 292 ns 286 ns 2240000
rng::generate_n(deque<int>)/8192 2291 ns 2302 ns 298667
```
2025-10-28 22:22:26 +08:00
Connector Switch
c06ae43e26
[libcxx] Optimize std::generate_n for segmented iterators ( #164266 )
...
Part of #102817 .
This is a natural follow-up to #163006 . We are forwarding
`std::generate_n` to `std::__for_each_n` (`std::for_each_n` needs
c++17), resulting in improved performance for segmented iterators.
before:
```
std::generate_n(deque<int>)/32 17.5 ns 17.3 ns 40727273
std::generate_n(deque<int>)/50 25.7 ns 25.5 ns 26352941
std::generate_n(deque<int>)/1024 490 ns 487 ns 1445161
std::generate_n(deque<int>)/8192 3908 ns 3924 ns 179200
```
after:
```
std::generate_n(deque<int>)/32 11.1 ns 11.0 ns 64000000
std::generate_n(deque<int>)/50 16.1 ns 16.0 ns 44800000
std::generate_n(deque<int>)/1024 291 ns 292 ns 2357895
std::generate_n(deque<int>)/8192 2269 ns 2250 ns 298667
```
2025-10-21 12:01:36 +02:00
Nikolas Klauser
253e435908
Reapply "[libc++] Optimize __hash_table::erase(iterator, iterator)" ( #162850 )
...
This reapplication fixes the use after free caused by not properly
updating the bucket list in one case.
Original commit message:
Instead of just calling the single element `erase` on every element of
the range, we can combine some of the operations in a custom
implementation. Specifically, we don't need to search for the previous
node or re-link the list every iteration. Removing this unnecessary work
results in some nice performance improvements:
```
-----------------------------------------------------------------------------------------------------------------------
Benchmark old new
-----------------------------------------------------------------------------------------------------------------------
std::unordered_set<int>::erase(iterator, iterator) (erase half the container)/0 457 ns 459 ns
std::unordered_set<int>::erase(iterator, iterator) (erase half the container)/32 995 ns 626 ns
std::unordered_set<int>::erase(iterator, iterator) (erase half the container)/1024 18196 ns 7995 ns
std::unordered_set<int>::erase(iterator, iterator) (erase half the container)/8192 124722 ns 70125 ns
std::unordered_set<std::string>::erase(iterator, iterator) (erase half the container)/0 456 ns 461 ns
std::unordered_set<std::string>::erase(iterator, iterator) (erase half the container)/32 1183 ns 769 ns
std::unordered_set<std::string>::erase(iterator, iterator) (erase half the container)/1024 27827 ns 18614 ns
std::unordered_set<std::string>::erase(iterator, iterator) (erase half the container)/8192 266681 ns 226107 ns
std::unordered_map<int, int>::erase(iterator, iterator) (erase half the container)/0 455 ns 462 ns
std::unordered_map<int, int>::erase(iterator, iterator) (erase half the container)/32 996 ns 659 ns
std::unordered_map<int, int>::erase(iterator, iterator) (erase half the container)/1024 15963 ns 8108 ns
std::unordered_map<int, int>::erase(iterator, iterator) (erase half the container)/8192 136493 ns 71848 ns
std::unordered_multiset<int>::erase(iterator, iterator) (erase half the container)/0 454 ns 455 ns
std::unordered_multiset<int>::erase(iterator, iterator) (erase half the container)/32 985 ns 703 ns
std::unordered_multiset<int>::erase(iterator, iterator) (erase half the container)/1024 16277 ns 9085 ns
std::unordered_multiset<int>::erase(iterator, iterator) (erase half the container)/8192 125736 ns 82710 ns
std::unordered_multimap<int, int>::erase(iterator, iterator) (erase half the container)/0 457 ns 454 ns
std::unordered_multimap<int, int>::erase(iterator, iterator) (erase half the container)/32 1091 ns 646 ns
std::unordered_multimap<int, int>::erase(iterator, iterator) (erase half the container)/1024 17784 ns 7664 ns
std::unordered_multimap<int, int>::erase(iterator, iterator) (erase half the container)/8192 127098 ns 72806 ns
```
This reverts commit acc3a6234a91369b818fdd6482ded0ac32d8ffa6.
2025-10-21 10:20:06 +02:00
Connector Switch
46e8816928
[libcxx] Optimize std::generate for segmented iterators ( #163006 )
...
Part of #102817 .
This patch attempts to optimize the performance of `std::generate` for
segmented iterators. Below are the benchmark numbers from
`libcxx\test\benchmarks\algorithms\modifying\generate.bench.cpp`. Test
cases that use segmented iterators have also been added.
- before
```
std::generate(deque<int>)/32 194 ns 193 ns 3733333
std::generate(deque<int>)/50 276 ns 276 ns 2488889
std::generate(deque<int>)/1024 5096 ns 5022 ns 112000
std::generate(deque<int>)/8192 40806 ns 40806 ns 17231
```
- after
```
std::generate(deque<int>)/32 106 ns 105 ns 6400000
std::generate(deque<int>)/50 139 ns 138 ns 4977778
std::generate(deque<int>)/1024 2713 ns 2699 ns 248889
std::generate(deque<int>)/8192 18983 ns 19252 ns 37333
```
---------
Co-authored-by: A. Jiang <de34@live.cn>
2025-10-20 19:37:33 +08:00
A. Jiang
cecde43009
[libc++][docs] Retarget completion of P2944R3 to LLVM 22 ( #163753 )
...
The completion of P2944R3 (4a509f853fa4821ecdb0f6bc3b90ddd48794cc8c)
just missed LLVM 21 release, and it seems controversial that whether
such feature completion should be backported.
I'm aware of following-up cleanup and bugfix about `<tuple>`. Perhaps it
will become more and more unwise to backport the changes. So let's
retarget P2944R3 to LLVM 22 in documentations.
Drive-by: Also fixes the formatting of the entry of P3379R0.
2025-10-19 15:35:47 +08:00
Peng Liu
d0cee6939a
[libc++] Optimize std::{,ranges}::{fill,fill_n} for segmented iterators ( #132665 )
...
This patch optimizes `std::fill`, `std::fill_n`, `std::ranges::fill`,
and `std::ranges::fill_n` for segmented iterators, achieving substantial
performance improvements. Specifically, for `deque<int>` iterators, the
performance improvements are above 10x for all these algorithms. The
optimization also enables filling segmented memory of `deque<int>` to
approach the performance of filling contiguous memory of `vector<int>`.
Benchmark results comparing the before and after implementations are
provided below. For additional context, we’ve included `vector<int>`
results, which remain unchanged, as this patch specifically targets
segmented iterators and leaves non-segmented iterator behavior
untouched.
Fixes two subtasks outlined in #102817 .
#### `fill_n`
```
-----------------------------------------------------------------------------
Benchmark Before After Speedup
-----------------------------------------------------------------------------
std::fill_n(deque<int>)/32 11.4 ns 2.28 ns 5.0x
std::fill_n(deque<int>)/50 19.7 ns 3.40 ns 5.8x
std::fill_n(deque<int>)/1024 391 ns 37.3 ns 10.5x
std::fill_n(deque<int>)/8192 3174 ns 301 ns 10.5x
std::fill_n(deque<int>)/65536 26504 ns 2951 ns 9.0x
std::fill_n(deque<int>)/1048576 407960 ns 80658 ns 5.1x
rng::fill_n(deque<int>)/32 14.3 ns 2.15 ns 6.6x
rng::fill_n(deque<int>)/50 20.2 ns 3.22 ns 6.3x
rng::fill_n(deque<int>)/1024 381 ns 37.8 ns 10.1x
rng::fill_n(deque<int>)/8192 3101 ns 294 ns 10.5x
rng::fill_n(deque<int>)/65536 25098 ns 2926 ns 8.6x
rng::fill_n(deque<int>)/1048576 394342 ns 78874 ns 5.0x
std::fill_n(vector<int>)/32 1.76 ns 1.72 ns 1.0x
std::fill_n(vector<int>)/50 3.00 ns 2.73 ns 1.1x
std::fill_n(vector<int>)/1024 38.4 ns 37.9 ns 1.0x
std::fill_n(vector<int>)/8192 258 ns 252 ns 1.0x
std::fill_n(vector<int>)/65536 2993 ns 2889 ns 1.0x
std::fill_n(vector<int>)/1048576 80328 ns 80468 ns 1.0x
rng::fill_n(vector<int>)/32 1.99 ns 1.35 ns 1.5x
rng::fill_n(vector<int>)/50 2.66 ns 2.12 ns 1.3x
rng::fill_n(vector<int>)/1024 37.7 ns 35.8 ns 1.1x
rng::fill_n(vector<int>)/8192 253 ns 250 ns 1.0x
rng::fill_n(vector<int>)/65536 2922 ns 2930 ns 1.0x
rng::fill_n(vector<int>)/1048576 79739 ns 79742 ns 1.0x
```
#### `fill`
```
--------------------------------------------------------------------------
Benchmark Before After Speedup
--------------------------------------------------------------------------
std::fill(deque<int>)/32 13.7 ns 2.45 ns 5.6x
std::fill(deque<int>)/50 21.7 ns 4.57 ns 4.7x
std::fill(deque<int>)/1024 367 ns 38.5 ns 9.5x
std::fill(deque<int>)/8192 2896 ns 247 ns 11.7x
std::fill(deque<int>)/65536 23723 ns 2907 ns 8.2x
std::fill(deque<int>)/1048576 379043 ns 79885 ns 4.7x
rng::fill(deque<int>)/32 13.6 ns 2.70 ns 5.0x
rng::fill(deque<int>)/50 23.4 ns 3.94 ns 5.9x
rng::fill(deque<int>)/1024 377 ns 37.9 ns 9.9x
rng::fill(deque<int>)/8192 2914 ns 286 ns 10.2x
rng::fill(deque<int>)/65536 23612 ns 2939 ns 8.0x
rng::fill(deque<int>)/1048576 379841 ns 80079 ns 4.7x
std::fill(vector<int>)/32 1.99 ns 1.79 ns 1.1x
std::fill(vector<int>)/50 3.05 ns 3.06 ns 1.0x
std::fill(vector<int>)/1024 37.6 ns 38.0 ns 1.0x
std::fill(vector<int>)/8192 255 ns 257 ns 1.0x
std::fill(vector<int>)/65536 2966 ns 2981 ns 1.0x
std::fill(vector<int>)/1048576 78300 ns 80348 ns 1.0x
rng::fill(vector<int>)/32 1.77 ns 1.75 ns 1.0x
rng::fill(vector<int>)/50 4.85 ns 2.31 ns 2.1x
rng::fill(vector<int>)/1024 39.6 ns 36.1 ns 1.1x
rng::fill(vector<int>)/8192 238 ns 251 ns 0.9x
rng::fill(vector<int>)/65536 2941 ns 2918 ns 1.0x
rng::fill(vector<int>)/1048576 80497 ns 80442 ns 1.0x
```
---------
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
Co-authored-by: A. Jiang <de34@live.cn>
2025-10-17 07:41:24 +08:00
Peng Liu
fd08af0a96
[libc++] Optimize {std,ranges}::distance for segmented iterators ( #133612 )
...
This patch enhances the performance of `std::distance` and
`std::ranges::distance` for non-random-access segmented iterators, e.g.,
`std::join_view` iterators. The original implementation operates in
linear time, `O(n)`, where `n` is the total number of elements. The
optimized version reduces this to approximately `O(n / segment_size)` by
leveraging segmented structure, where `segment_size` is the average size
of each segment.
The table below summarizes the peak performance improvements observed
across different segment sizes, with the total element count `n` ranging
up to `1 << 20` (1,048,576 elements), based on benchmark results.
```
----------------------------------------------------------------------------------------
Container/n/segment_size std::distance std::ranges::distance
----------------------------------------------------------------------------------------
join_view(vector<vector<int>>)/1048576/256 401.6x 422.9x
join_view(deque<deque<int>>)/1048576/256 112.1x 132.6x
join_view(vector<vector<int>>)/1048576/1024 1669.2x 1559.1x
join_view(deque<deque<int>>)/1048576/1024 487.7x 497.4x
```
## Benchmarks
#### Segment size = 1024
```
-----------------------------------------------------------------------------------------
Benchmark Before After Speedup
-----------------------------------------------------------------------------------------
std::distance(join_view(vector<vector<int>>))/50 38.8 ns 1.01 ns 38.4x
std::distance(join_view(vector<vector<int>>))/1024 660 ns 1.02 ns 647.1x
std::distance(join_view(vector<vector<int>>))/4096 2934 ns 1.98 ns 1481.8x
std::distance(join_view(vector<vector<int>>))/8192 5751 ns 3.92 ns 1466.8x
std::distance(join_view(vector<vector<int>>))/16384 11520 ns 7.06 ns 1631.7x
std::distance(join_view(vector<vector<int>>))/65536 46367 ns 32.2 ns 1440.6x
std::distance(join_view(vector<vector<int>>))/262144 182611 ns 114 ns 1601.9x
std::distance(join_view(vector<vector<int>>))/1048576 737785 ns 442 ns 1669.2x
std::distance(join_view(deque<deque<int>>))/50 53.1 ns 6.13 ns 8.7x
std::distance(join_view(deque<deque<int>>))/1024 854 ns 7.53 ns 113.4x
std::distance(join_view(deque<deque<int>>))/4096 3507 ns 14.7 ns 238.6x
std::distance(join_view(deque<deque<int>>))/8192 7114 ns 17.6 ns 404.2x
std::distance(join_view(deque<deque<int>>))/16384 13997 ns 30.7 ns 455.9x
std::distance(join_view(deque<deque<int>>))/65536 55598 ns 114 ns 487.7x
std::distance(join_view(deque<deque<int>>))/262144 214293 ns 480 ns 446.4x
std::distance(join_view(deque<deque<int>>))/1048576 833000 ns 2183 ns 381.6x
rng::distance(join_view(vector<vector<int>>))/50 39.1 ns 1.10 ns 35.5x
rng::distance(join_view(vector<vector<int>>))/1024 689 ns 1.14 ns 604.4x
rng::distance(join_view(vector<vector<int>>))/4096 2753 ns 2.15 ns 1280.5x
rng::distance(join_view(vector<vector<int>>))/8192 5530 ns 4.61 ns 1199.6x
rng::distance(join_view(vector<vector<int>>))/16384 10968 ns 7.97 ns 1376.2x
rng::distance(join_view(vector<vector<int>>))/65536 46009 ns 35.3 ns 1303.4x
rng::distance(join_view(vector<vector<int>>))/262144 190569 ns 124 ns 1536.9x
rng::distance(join_view(vector<vector<int>>))/1048576 746724 ns 479 ns 1559.1x
rng::distance(join_view(deque<deque<int>>))/50 51.6 ns 6.57 ns 7.9x
rng::distance(join_view(deque<deque<int>>))/1024 826 ns 6.50 ns 127.1x
rng::distance(join_view(deque<deque<int>>))/4096 3323 ns 12.5 ns 265.8x
rng::distance(join_view(deque<deque<int>>))/8192 6619 ns 19.1 ns 346.5x
rng::distance(join_view(deque<deque<int>>))/16384 13495 ns 33.2 ns 406.5x
rng::distance(join_view(deque<deque<int>>))/65536 53668 ns 114 ns 470.8x
rng::distance(join_view(deque<deque<int>>))/262144 236277 ns 475 ns 497.4x
rng::distance(join_view(deque<deque<int>>))/1048576 914177 ns 2157 ns 423.8x
-----------------------------------------------------------------------------------------
```
#### Segment size = 256
```
-----------------------------------------------------------------------------------------
Benchmark Before After Speedup
-----------------------------------------------------------------------------------------
std::distance(join_view(vector<vector<int>>))/50 38.1 ns 1.02 ns 37.4x
std::distance(join_view(vector<vector<int>>))/1024 689 ns 2.06 ns 334.5x
std::distance(join_view(vector<vector<int>>))/4096 2815 ns 7.01 ns 401.6x
std::distance(join_view(vector<vector<int>>))/8192 5507 ns 14.3 ns 385.1x
std::distance(join_view(vector<vector<int>>))/16384 11050 ns 33.7 ns 327.9x
std::distance(join_view(vector<vector<int>>))/65536 44197 ns 118 ns 374.6x
std::distance(join_view(vector<vector<int>>))/262144 175793 ns 449 ns 391.5x
std::distance(join_view(vector<vector<int>>))/1048576 703242 ns 2140 ns 328.7x
std::distance(join_view(deque<deque<int>>))/50 50.2 ns 6.12 ns 8.2x
std::distance(join_view(deque<deque<int>>))/1024 835 ns 11.4 ns 73.2x
std::distance(join_view(deque<deque<int>>))/4096 3353 ns 32.9 ns 101.9x
std::distance(join_view(deque<deque<int>>))/8192 6711 ns 64.2 ns 104.5x
std::distance(join_view(deque<deque<int>>))/16384 13231 ns 118 ns 112.1x
std::distance(join_view(deque<deque<int>>))/65536 53523 ns 556 ns 96.3x
std::distance(join_view(deque<deque<int>>))/262144 219101 ns 2166 ns 101.2x
std::distance(join_view(deque<deque<int>>))/1048576 880277 ns 15852 ns 55.5x
rng::distance(join_view(vector<vector<int>>))/50 37.7 ns 1.13 ns 33.4x
rng::distance(join_view(vector<vector<int>>))/1024 697 ns 2.14 ns 325.7x
rng::distance(join_view(vector<vector<int>>))/4096 2804 ns 7.52 ns 373.0x
rng::distance(join_view(vector<vector<int>>))/8192 5749 ns 15.2 ns 378.2x
rng::distance(join_view(vector<vector<int>>))/16384 11742 ns 34.8 ns 337.4x
rng::distance(join_view(vector<vector<int>>))/65536 47274 ns 116 ns 407.7x
rng::distance(join_view(vector<vector<int>>))/262144 187774 ns 444 ns 422.9x
rng::distance(join_view(vector<vector<int>>))/1048576 749724 ns 2109 ns 355.5x
rng::distance(join_view(deque<deque<int>>))/50 53.0 ns 6.09 ns 8.7x
rng::distance(join_view(deque<deque<int>>))/1024 895 ns 11.0 ns 81.4x
rng::distance(join_view(deque<deque<int>>))/4096 3825 ns 30.6 ns 125.0x
rng::distance(join_view(deque<deque<int>>))/8192 7550 ns 60.5 ns 124.8x
rng::distance(join_view(deque<deque<int>>))/16384 14847 ns 112 ns 132.6x
rng::distance(join_view(deque<deque<int>>))/65536 56888 ns 453 ns 125.6x
rng::distance(join_view(deque<deque<int>>))/262144 231395 ns 2034 ns 113.8x
rng::distance(join_view(deque<deque<int>>))/1048576 933093 ns 15012 ns 62.2x
-----------------------------------------------------------------------------------------
```
Addresses a subtask of #102817 .
---------
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
Co-authored-by: A. Jiang <de34@live.cn>
2025-10-16 07:44:35 +08:00
Hristo Hristov
8a27b48122
[libc++][atomic] P2835R7: Expose std::atomic_ref's object address ( #162236 )
...
Implements https://wg21.link/P2835R7
Closes #118377
# References
- https://wg21.link/atomics.ref.generic.general
- https://wg21.link/atomics.ref.int
- https://wg21.link/atomics.ref.float
- https://wg21.link/atomics.ref.pointer
---------
Co-authored-by: Hristo Hristov <zingam@outlook.com>
2025-10-13 20:27:02 +08:00
Hristo Hristov
45c41247f8
[libc++][ranges] P3060R3: Add std::views::indices(n) ( #146823 )
...
Implements [P3060R3](https://wg21.link/P3060R3 )
Closes #148175
# References
- https://github.com/cplusplus/draft/issues/7966
- https://github.com/cplusplus/draft/pull/8006
- https://wg21.link/customization.point.object
- https://wg21.link/range.iota.overview
- https://wg21.link/ranges.syn
---------
Co-authored-by: Hristo Hristov <zingam@outlook.com>
Co-authored-by: A. Jiang <de34@live.cn>
2025-10-06 18:13:25 +03:00
Hristo Hristov
ccd06e4809
[libc++][istream] P3223R2: Making std::istream::ignore less surprising ( #147007 )
...
Implements https://wg21.link/P3223R2 as a DR as, as recommended in
https://github.com/cplusplus/papers/issues/1871#issuecomment-2993018698 .
Resolves -1L ambiguity.
Closes #148178
2025-09-30 11:26:30 -04:00
Nikolas Klauser
97367d1046
[libc++] Vectorize std::find ( #156431 )
...
```
Apple M4:
-----------------------------------------------------------------------------
Benchmark old new
-----------------------------------------------------------------------------
std::find(vector<char>) (bail 25%)/8 1.43 ns 1.44 ns
std::find(vector<char>) (bail 25%)/1024 5.54 ns 5.59 ns
std::find(vector<char>) (bail 25%)/8192 38.4 ns 39.1 ns
std::find(vector<char>) (bail 25%)/32768 134 ns 136 ns
std::find(vector<int>) (bail 25%)/8 1.56 ns 1.57 ns
std::find(vector<int>) (bail 25%)/1024 65.3 ns 65.4 ns
std::find(vector<int>) (bail 25%)/8192 465 ns 464 ns
std::find(vector<int>) (bail 25%)/32768 1832 ns 1832 ns
std::find(vector<long long>) (bail 25%)/8 0.920 ns 1.20 ns
std::find(vector<long long>) (bail 25%)/1024 65.2 ns 31.2 ns
std::find(vector<long long>) (bail 25%)/8192 464 ns 255 ns
std::find(vector<long long>) (bail 25%)/32768 1833 ns 992 ns
std::find(vector<char>) (process all)/8 1.21 ns 1.22 ns
std::find(vector<char>) (process all)/50 1.92 ns 1.93 ns
std::find(vector<char>) (process all)/1024 16.6 ns 16.9 ns
std::find(vector<char>) (process all)/8192 134 ns 136 ns
std::find(vector<char>) (process all)/32768 488 ns 503 ns
std::find(vector<int>) (process all)/8 2.45 ns 2.48 ns
std::find(vector<int>) (process all)/50 12.7 ns 12.7 ns
std::find(vector<int>) (process all)/1024 236 ns 236 ns
std::find(vector<int>) (process all)/8192 1830 ns 1834 ns
std::find(vector<int>) (process all)/32768 7351 ns 7346 ns
std::find(vector<long long>) (process all)/8 2.02 ns 1.45 ns
std::find(vector<long long>) (process all)/50 12.0 ns 6.12 ns
std::find(vector<long long>) (process all)/1024 235 ns 123 ns
std::find(vector<long long>) (process all)/8192 1830 ns 983 ns
std::find(vector<long long>) (process all)/32768 7306 ns 3969 ns
std::find(vector<bool>) (process all)/8 1.14 ns 1.15 ns
std::find(vector<bool>) (process all)/50 1.16 ns 1.17 ns
std::find(vector<bool>) (process all)/1024 4.51 ns 4.53 ns
std::find(vector<bool>) (process all)/8192 33.6 ns 33.5 ns
std::find(vector<bool>) (process all)/1048576 3660 ns 3660 ns
```
2025-09-29 11:10:19 +02:00
Hristo Hristov
804b46bb45
[libc++][string] P3044R2: sub-string_view from string ( #147095 )
...
Implements [P3044R2](https://wg21.link/P3044R2 )
Note: `substr.pass.cpp` is refactored to accommodate the test of
`basic_string_view`'s `subview` which is an alias of `substr` without
changing the test cases.
Closes #148140
# References
- https://github.com/cplusplus/draft/pull/7975
- https://wg21.link/string.substr
- https://wg21.link/string.view.ops
---------
Co-authored-by: Hristo Hristov <zingam@outlook.com>
Co-authored-by: Nikolas Klauser <nikolasklauser@berlin.de>
2025-09-25 03:08:15 +03:00
Nikolas Klauser
868aa5f19c
[libc++] Introduce _LIBCPP_COMPRESSED_ELEMENT ( #134253 )
...
We have multiple classes with an empty base optimization that contains
just a single type. This patch introduces `_LIBCPP_COMPRESSED_ELEMENT`
to refactor these classes to avoid having them essentially twice,
reducing the amount of code significantly.
2025-09-18 14:31:18 +02:00
Aiden Grossman
acc3a6234a
Revert "[libc++] Optimize __hash_table::erase(iterator, iterator) (#1… ( #158769 )
...
…52471)"
This reverts commit e4eccd6a3c2415c10bb8217c247d7aca76cc9ad5.
This was causing ASan failures in some situations involving unordered
multimap containers. Details and a reproducer were posted on the
original PR (#152471 ).
2025-09-17 07:52:49 -07:00
Nikolas Klauser
34d4f0c136
[libc++][NFC] Use llvm.org/PR to link to bug reports ( #156288 )
...
We've built up quite a few links directly to github within the code
base. We should instead use `llvm.org/PR<issue-number>` to link to bugs,
since that is resilient to the bug tracker changing in the future. This
is especially relevant for tests linking to bugs, since they will
probably be there for decades to come. A nice side effect is that these
links are significantly shorter than the GH links, making them much less
of an eyesore.
This patch also replaces a few links that linked to the old bugzilla
instance on llvm.org.
2025-09-04 09:20:02 +02:00
Nikolas Klauser
e8fa13ca4e
[libc++] Split ABI flag for removing iterator bases and removing the second member in reverse_iterator ( #143079 )
...
Currently `_LIBCPP_NO_ITERATOR_BASES` controls both whether specific
classes derive from `iterator` and whether `reverse_iterator` has a
second member variable. These two changes are orthogonal though, and one
can be applied in all langauge modes while the other change is only
conforming for C++17 and later.
2025-09-04 09:18:49 +02:00
Nikolas Klauser
7624c61419
[libc++] Optimize {map,set}::insert(InputIterator, InputIterator) ( #154703 )
...
```
----------------------------------------------------------------------------------------------------------------------------
Benchmark old new
----------------------------------------------------------------------------------------------------------------------------
std::map<int, int>::ctor(iterator, iterator) (unsorted sequence)/0 14.2 ns 14.8 ns
std::map<int, int>::ctor(iterator, iterator) (unsorted sequence)/32 519 ns 404 ns
std::map<int, int>::ctor(iterator, iterator) (unsorted sequence)/1024 52460 ns 36242 ns
std::map<int, int>::ctor(iterator, iterator) (unsorted sequence)/8192 724222 ns 706496 ns
std::map<int, int>::ctor(iterator, iterator) (sorted sequence)/0 14.2 ns 14.7 ns
std::map<int, int>::ctor(iterator, iterator) (sorted sequence)/32 429 ns 349 ns
std::map<int, int>::ctor(iterator, iterator) (sorted sequence)/1024 23601 ns 14734 ns
std::map<int, int>::ctor(iterator, iterator) (sorted sequence)/8192 267753 ns 112155 ns
std::map<int, int>::insert(iterator, iterator) (all new keys)/0 434 ns 448 ns
std::map<int, int>::insert(iterator, iterator) (all new keys)/32 950 ns 963 ns
std::map<int, int>::insert(iterator, iterator) (all new keys)/1024 27205 ns 25344 ns
std::map<int, int>::insert(iterator, iterator) (all new keys)/8192 294248 ns 280713 ns
std::map<int, int>::insert(iterator, iterator) (half new keys)/0 435 ns 449 ns
std::map<int, int>::insert(iterator, iterator) (half new keys)/32 771 ns 706 ns
std::map<int, int>::insert(iterator, iterator) (half new keys)/1024 30841 ns 17495 ns
std::map<int, int>::insert(iterator, iterator) (half new keys)/8192 468807 ns 285847 ns
std::map<int, int>::insert(iterator, iterator) (product_iterator from same type)/0 449 ns 453 ns
std::map<int, int>::insert(iterator, iterator) (product_iterator from same type)/32 1021 ns 932 ns
std::map<int, int>::insert(iterator, iterator) (product_iterator from same type)/1024 29796 ns 19518 ns
std::map<int, int>::insert(iterator, iterator) (product_iterator from same type)/8192 345688 ns 153966 ns
std::map<int, int>::insert(iterator, iterator) (product_iterator from zip_view)/0 449 ns 450 ns
std::map<int, int>::insert(iterator, iterator) (product_iterator from zip_view)/32 1026 ns 807 ns
std::map<int, int>::insert(iterator, iterator) (product_iterator from zip_view)/1024 31632 ns 15573 ns
std::map<int, int>::insert(iterator, iterator) (product_iterator from zip_view)/8192 303024 ns 128946 ns
std::map<int, int>::erase(iterator, iterator) (erase half the container)/0 447 ns 452 ns
std::map<int, int>::erase(iterator, iterator) (erase half the container)/32 687 ns 710 ns
std::map<int, int>::erase(iterator, iterator) (erase half the container)/1024 8604 ns 8581 ns
std::map<int, int>::erase(iterator, iterator) (erase half the container)/8192 65693 ns 67406 ns
std::map<std::string, int>::ctor(iterator, iterator) (unsorted sequence)/0 15.0 ns 15.0 ns
std::map<std::string, int>::ctor(iterator, iterator) (unsorted sequence)/32 2781 ns 1845 ns
std::map<std::string, int>::ctor(iterator, iterator) (unsorted sequence)/1024 187999 ns 182103 ns
std::map<std::string, int>::ctor(iterator, iterator) (unsorted sequence)/8192 2937242 ns 2934912 ns
std::map<std::string, int>::ctor(iterator, iterator) (sorted sequence)/0 15.0 ns 15.2 ns
std::map<std::string, int>::ctor(iterator, iterator) (sorted sequence)/32 1326 ns 2462 ns
std::map<std::string, int>::ctor(iterator, iterator) (sorted sequence)/1024 81778 ns 72193 ns
std::map<std::string, int>::ctor(iterator, iterator) (sorted sequence)/8192 1177292 ns 669152 ns
std::map<std::string, int>::insert(iterator, iterator) (all new keys)/0 439 ns 454 ns
std::map<std::string, int>::insert(iterator, iterator) (all new keys)/32 2483 ns 2465 ns
std::map<std::string, int>::insert(iterator, iterator) (all new keys)/1024 187614 ns 188072 ns
std::map<std::string, int>::insert(iterator, iterator) (all new keys)/8192 1654675 ns 1706603 ns
std::map<std::string, int>::insert(iterator, iterator) (half new keys)/0 437 ns 452 ns
std::map<std::string, int>::insert(iterator, iterator) (half new keys)/32 1836 ns 1820 ns
std::map<std::string, int>::insert(iterator, iterator) (half new keys)/1024 114885 ns 121865 ns
std::map<std::string, int>::insert(iterator, iterator) (half new keys)/8192 1151960 ns 1197318 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from same type)/0 438 ns 455 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from same type)/32 1599 ns 1614 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from same type)/1024 95935 ns 82159 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from same type)/8192 776480 ns 941043 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from zip_view)/0 435 ns 462 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from zip_view)/32 1723 ns 1550 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from zip_view)/1024 107096 ns 92850 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from zip_view)/8192 893976 ns 775046 ns
std::map<std::string, int>::erase(iterator, iterator) (erase half the container)/0 436 ns 453 ns
std::map<std::string, int>::erase(iterator, iterator) (erase half the container)/32 775 ns 824 ns
std::map<std::string, int>::erase(iterator, iterator) (erase half the container)/1024 20241 ns 20454 ns
std::map<std::string, int>::erase(iterator, iterator) (erase half the container)/8192 139038 ns 138032 ns
std::set<int>::ctor(iterator, iterator) (unsorted sequence)/0 14.8 ns 14.7 ns
std::set<int>::ctor(iterator, iterator) (unsorted sequence)/32 468 ns 426 ns
std::set<int>::ctor(iterator, iterator) (unsorted sequence)/1024 54289 ns 39028 ns
std::set<int>::ctor(iterator, iterator) (unsorted sequence)/8192 738438 ns 695720 ns
std::set<int>::ctor(iterator, iterator) (sorted sequence)/0 14.7 ns 14.6 ns
std::set<int>::ctor(iterator, iterator) (sorted sequence)/32 478 ns 391 ns
std::set<int>::ctor(iterator, iterator) (sorted sequence)/1024 24017 ns 13905 ns
std::set<int>::ctor(iterator, iterator) (sorted sequence)/8192 267862 ns 111378 ns
std::set<int>::insert(iterator, iterator) (all new keys)/0 458 ns 450 ns
std::set<int>::insert(iterator, iterator) (all new keys)/32 1066 ns 956 ns
std::set<int>::insert(iterator, iterator) (all new keys)/1024 29190 ns 25212 ns
std::set<int>::insert(iterator, iterator) (all new keys)/8192 320441 ns 279602 ns
std::set<int>::insert(iterator, iterator) (half new keys)/0 454 ns 453 ns
std::set<int>::insert(iterator, iterator) (half new keys)/32 816 ns 709 ns
std::set<int>::insert(iterator, iterator) (half new keys)/1024 32072 ns 17074 ns
std::set<int>::insert(iterator, iterator) (half new keys)/8192 403386 ns 286202 ns
std::set<int>::erase(iterator, iterator) (erase half the container)/0 451 ns 452 ns
std::set<int>::erase(iterator, iterator) (erase half the container)/32 710 ns 703 ns
std::set<int>::erase(iterator, iterator) (erase half the container)/1024 8261 ns 8499 ns
std::set<int>::erase(iterator, iterator) (erase half the container)/8192 64466 ns 67343 ns
std::set<std::string>::ctor(iterator, iterator) (unsorted sequence)/0 15.2 ns 15.0 ns
std::set<std::string>::ctor(iterator, iterator) (unsorted sequence)/32 3069 ns 3005 ns
std::set<std::string>::ctor(iterator, iterator) (unsorted sequence)/1024 189552 ns 180933 ns
std::set<std::string>::ctor(iterator, iterator) (unsorted sequence)/8192 2887579 ns 2691678 ns
std::set<std::string>::ctor(iterator, iterator) (sorted sequence)/0 15.1 ns 14.9 ns
std::set<std::string>::ctor(iterator, iterator) (sorted sequence)/32 2611 ns 2514 ns
std::set<std::string>::ctor(iterator, iterator) (sorted sequence)/1024 91581 ns 78727 ns
std::set<std::string>::ctor(iterator, iterator) (sorted sequence)/8192 1192640 ns 1158959 ns
std::set<std::string>::insert(iterator, iterator) (all new keys)/0 452 ns 457 ns
std::set<std::string>::insert(iterator, iterator) (all new keys)/32 2530 ns 2544 ns
std::set<std::string>::insert(iterator, iterator) (all new keys)/1024 195352 ns 179614 ns
std::set<std::string>::insert(iterator, iterator) (all new keys)/8192 1737890 ns 1749615 ns
std::set<std::string>::insert(iterator, iterator) (half new keys)/0 451 ns 454 ns
std::set<std::string>::insert(iterator, iterator) (half new keys)/32 1949 ns 1766 ns
std::set<std::string>::insert(iterator, iterator) (half new keys)/1024 128853 ns 109467 ns
std::set<std::string>::insert(iterator, iterator) (half new keys)/8192 1233077 ns 1177289 ns
std::set<std::string>::erase(iterator, iterator) (erase half the container)/0 450 ns 451 ns
std::set<std::string>::erase(iterator, iterator) (erase half the container)/32 809 ns 812 ns
std::set<std::string>::erase(iterator, iterator) (erase half the container)/1024 21736 ns 21922 ns
std::set<std::string>::erase(iterator, iterator) (erase half the container)/8192 135884 ns 133228 ns
```
Fixes #154650
2025-09-03 08:15:29 +02:00
Nikolas Klauser
4c5877dbc2
[libc++] Optimize map::insert_or_assign ( #155816 )
...
`__emplace_unique` uses `__find_equal`, which can be significantly
faster than `lower_bound`. As a nice side-effect, this also changes the
implementation to the "naive" implementation of trying `insert` first,
and if that fails assign instead. This also matches the
`insert_or_assign` overloads with a hint.
```
Zen 2:
--------------------------------------------------------------------------------------------------------
Benchmark old new
--------------------------------------------------------------------------------------------------------
std::map<int, int>::insert_or_assign(key, value) (already present)/0 1.62 ns 1.53 ns
std::map<int, int>::insert_or_assign(key, value) (already present)/32 5.78 ns 5.99 ns
std::map<int, int>::insert_or_assign(key, value) (already present)/1024 21.5 ns 15.4 ns
std::map<int, int>::insert_or_assign(key, value) (already present)/8192 26.2 ns 20.5 ns
std::map<int, int>::insert_or_assign(key, value) (new value)/0 22.5 ns 21.1 ns
std::map<int, int>::insert_or_assign(key, value) (new value)/32 42.9 ns 28.4 ns
std::map<int, int>::insert_or_assign(key, value) (new value)/1024 118 ns 92.0 ns
std::map<int, int>::insert_or_assign(key, value) (new value)/8192 227 ns 173 ns
std::map<std::string, int>::insert_or_assign(key, value) (already present)/0 13.2 ns 18.9 ns
std::map<std::string, int>::insert_or_assign(key, value) (already present)/32 65.6 ns 39.0 ns
std::map<std::string, int>::insert_or_assign(key, value) (already present)/1024 127 ns 64.4 ns
std::map<std::string, int>::insert_or_assign(key, value) (already present)/8192 134 ns 71.4 ns
std::map<std::string, int>::insert_or_assign(key, value) (new value)/0 45.6 ns 37.3 ns
std::map<std::string, int>::insert_or_assign(key, value) (new value)/32 142 ns 93.3 ns
std::map<std::string, int>::insert_or_assign(key, value) (new value)/1024 288 ns 147 ns
std::map<std::string, int>::insert_or_assign(key, value) (new value)/8192 368 ns 182 ns
Apple M4:
--------------------------------------------------------------------------------------------------------
Benchmark old new
--------------------------------------------------------------------------------------------------------
std::map<int, int>::insert_or_assign(key, value) (already present)/0 0.784 ns 0.740 ns
std::map<int, int>::insert_or_assign(key, value) (already present)/32 2.52 ns 1.77 ns
std::map<int, int>::insert_or_assign(key, value) (already present)/1024 8.72 ns 4.06 ns
std::map<int, int>::insert_or_assign(key, value) (already present)/8192 10.6 ns 3.98 ns
std::map<int, int>::insert_or_assign(key, value) (new value)/0 17.3 ns 17.2 ns
std::map<int, int>::insert_or_assign(key, value) (new value)/32 22.5 ns 19.3 ns
std::map<int, int>::insert_or_assign(key, value) (new value)/1024 56.8 ns 33.5 ns
std::map<int, int>::insert_or_assign(key, value) (new value)/8192 88.2 ns 41.0 ns
std::map<std::string, int>::insert_or_assign(key, value) (already present)/0 16.6 ns 11.8 ns
std::map<std::string, int>::insert_or_assign(key, value) (already present)/32 13.7 ns 30.7 ns
std::map<std::string, int>::insert_or_assign(key, value) (already present)/1024 46.7 ns 49.1 ns
std::map<std::string, int>::insert_or_assign(key, value) (already present)/8192 41.9 ns 76.9 ns
std::map<std::string, int>::insert_or_assign(key, value) (new value)/0 40.0 ns 40.5 ns
std::map<std::string, int>::insert_or_assign(key, value) (new value)/32 38.9 ns 40.0 ns
std::map<std::string, int>::insert_or_assign(key, value) (new value)/1024 84.9 ns 96.9 ns
std::map<std::string, int>::insert_or_assign(key, value) (new value)/8192 166 ns 149 ns
```
2025-08-29 18:48:11 +02:00
Nikolas Klauser
c5949f74bf
[libc++] Optimize ofstream::write ( #123337 )
...
```
----------------------------
Benchmark old new
----------------------------
bm_write 1382 ns 521 ns
```
2025-08-27 14:50:37 +02:00
Nikolas Klauser
83583b211e
[libc++][NFC] Wrap lines in ReleaseNotes/22.rst ( #155359 )
...
Some of the lines in `ReleaseNotes/22.rst` are (significantly) longer
than our usual 120 column limit. This wraps all lines in the file so
they are never more than our usual limit.
2025-08-26 09:10:41 +02:00