[libcxx-commits] [libcxx] [libc++] fix minor performance issue in `basic_string<C>::append()` (PR #210078)

Pavel Novikov via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 17 07:12:09 PDT 2026


toughengineer wrote:

Here's a reasonable and realistic (in my opinion) example:
```c++
// given some string like input, e.g.
std::string_view input;
// and also some locale and output
std::locale locale;
std::string output;
// ...
auto p = input |
  std::views::filter([&locale](char c) { return std::isprint(c, locale); });
output.append(p.begin(), p.end());
```
Even this almost trivial example demostrates the performance issue:
<img width="1210" height="681" alt="ranges" src="https://github.com/user-attachments/assets/9a812657-cca9-47b2-a979-7656c9ec68e5" />
<details><summary>benchmark output before</summary>

```
2026-07-17T16:36:18+03:00
Running ./string_append
Run on (20 X 3494.4 MHz CPU s)
CPU Caches:
  L1 Data 48 KiB (x10)
  L1 Instruction 32 KiB (x10)
  L2 Unified 2048 KiB (x10)
  L3 Unified 24576 KiB (x1)
Load Average: 0.36, 0.18, 0.16
-------------------------------------------------------------------------------
Benchmark                     Time             CPU   Iterations UserCounters...
-------------------------------------------------------------------------------
bench_ranges/1             9.03 ns         9.03 ns     79388662 t/i=9.031ns
bench_ranges/2             19.7 ns         19.7 ns     35723581 t/i=9.84356ns
bench_ranges/4             36.1 ns         36.1 ns     19531441 t/i=9.0152ns
bench_ranges/8             69.0 ns         69.0 ns      9956207 t/i=8.62202ns
bench_ranges/16             125 ns          125 ns      5613594 t/i=7.84345ns
bench_ranges/32             247 ns          247 ns      2822421 t/i=7.72773ns
bench_ranges/64             516 ns          516 ns      1372805 t/i=8.05528ns
bench_ranges/128            992 ns          992 ns       694859 t/i=7.75294ns
bench_ranges/256           1958 ns         1958 ns       351618 t/i=7.6484ns
bench_ranges/512           3927 ns         3927 ns       179205 t/i=7.66954ns
bench_ranges/1024          7838 ns         7838 ns        90166 t/i=7.65432ns
bench_ranges/2048         21615 ns        21615 ns        32478 t/i=10.5541ns
bench_ranges/4096         52982 ns        52980 ns        13421 t/i=12.9345ns
bench_ranges/8192        117859 ns       117857 ns         6034 t/i=14.3868ns
bench_ranges/16384       255739 ns       255729 ns         2737 t/i=15.6085ns
bench_ranges/32768       527432 ns       527419 ns         1344 t/i=16.0956ns
bench_ranges/65536      1070200 ns      1070150 ns          641 t/i=16.3292ns
bench_ranges/131072     2134541 ns      2134475 ns          322 t/i=16.2848ns
bench_ranges/262144     4311675 ns      4311642 ns          164 t/i=16.4476ns
bench_ranges/524288     8571076 ns      8570984 ns           81 t/i=16.3479ns
bench_ranges/1048576   17185996 ns     17185873 ns           41 t/i=16.3897ns
```

</details>
<details><summary>benchmark output after</summary>

```
2026-07-17T16:37:09+03:00
Running ./string_append
Run on (20 X 3494.4 MHz CPU s)
CPU Caches:
  L1 Data 48 KiB (x10)
  L1 Instruction 32 KiB (x10)
  L2 Unified 2048 KiB (x10)
  L3 Unified 24576 KiB (x1)
Load Average: 0.39, 0.22, 0.18
-------------------------------------------------------------------------------
Benchmark                     Time             CPU   Iterations UserCounters...
-------------------------------------------------------------------------------
bench_ranges/1             8.40 ns         8.40 ns     86345986 t/i=8.40176ns
bench_ranges/2             15.6 ns         15.6 ns     44261217 t/i=7.80893ns
bench_ranges/4             26.5 ns         26.5 ns     26726279 t/i=6.61509ns
bench_ranges/8             49.7 ns         49.7 ns     14098475 t/i=6.20786ns
bench_ranges/16            85.9 ns         85.9 ns      8259402 t/i=5.36759ns
bench_ranges/32             169 ns          169 ns      3998519 t/i=5.27777ns
bench_ranges/64             349 ns          349 ns      1987558 t/i=5.45099ns
bench_ranges/128            683 ns          683 ns      1039694 t/i=5.33238ns
bench_ranges/256           1338 ns         1338 ns       517963 t/i=5.22682ns
bench_ranges/512           2631 ns         2631 ns       266303 t/i=5.13823ns
bench_ranges/1024          5245 ns         5245 ns       133538 t/i=5.1224ns
bench_ranges/2048         10921 ns        10920 ns        64641 t/i=5.33222ns
bench_ranges/4096         29330 ns        29329 ns        23693 t/i=7.16048ns
bench_ranges/8192         71116 ns        71114 ns         9436 t/i=8.68086ns
bench_ranges/16384       163212 ns       163205 ns         4357 t/i=9.96126ns
bench_ranges/32768       343948 ns       343942 ns         2012 t/i=10.4963ns
bench_ranges/65536       699559 ns       699560 ns          958 t/i=10.6744ns
bench_ranges/131072     1416766 ns      1416731 ns          497 t/i=10.8088ns
bench_ranges/262144     2861586 ns      2861507 ns          243 t/i=10.9158ns
bench_ranges/524288     5745899 ns      5745906 ns          120 t/i=10.9594ns
bench_ranges/1048576   11501892 ns     11501800 ns           62 t/i=10.969ns
```

</details>

In general the performance difference may be unbounded due to unbounded complexity of the processing.

The code may be garbage (like in this example), but I think you should not penalize the code on top of that.

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


More information about the libcxx-commits mailing list