[llvm-branch-commits] [libcxx] [libc++][format][4/7] Improves std::format_to performance. (PR #101823)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Aug 3 06:55:52 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

<details>
<summary>Changes</summary>

This changes the __output_buffer users for format_to to the new structure. It also uses the new allocating buffer to improve performance.

write_double_comparison:

Before
----------------------------------------------------------------------------------------
Benchmark                                              Time             CPU   Iterations
----------------------------------------------------------------------------------------
BM_sprintf                                           197 ns          197 ns      3537000
BM_to_string                                         219 ns          219 ns      3200000
BM_to_chars                                         42.3 ns         42.3 ns     16490000
BM_to_chars_as_string                               48.1 ns         48.1 ns     14508000
BM_format                                            167 ns          167 ns      4207000
BM_format_to_back_inserter<std::string>              179 ns          179 ns      3914000
BM_format_to_back_inserter<std::vector<char>>        216 ns          216 ns      3234000
BM_format_to_back_inserter<std::list<char>>          752 ns          752 ns       932000
BM_format_to_iterator/<std::array>                   165 ns          165 ns      4257000
BM_format_to_iterator/<std::string>                  165 ns          165 ns      4251000
BM_format_to_iterator/<std::vector>                  165 ns          165 ns      4254000

After
----------------------------------------------------------------------------------------
Benchmark                                              Time             CPU   Iterations
----------------------------------------------------------------------------------------
BM_sprintf                                           197 ns          197 ns      3548000
BM_to_string                                         219 ns          219 ns      3203000
BM_to_chars                                         42.3 ns         42.3 ns     16540000
BM_to_chars_as_string                               48.2 ns         48.2 ns     14532000
BM_format                                            167 ns          167 ns      4190000
BM_format_to_back_inserter<std::string>              176 ns          176 ns      3959000
BM_format_to_back_inserter<std::vector<char>>        211 ns          211 ns      3312000
BM_format_to_back_inserter<std::list<char>>          752 ns          752 ns       934000
BM_format_to_iterator/<std::array>                   162 ns          162 ns      4313000
BM_format_to_iterator/<std::string>                  162 ns          162 ns      4307000
BM_format_to_iterator/<std::vector>                  162 ns          162 ns      4308000

Comparison
Benchmark                                                       Time             CPU      Time Old      Time New       CPU Old       CPU New
--------------------------------------------------------------------------------------------------------------------------------------------
BM_sprintf                                                   +0.0003         +0.0002           197           197           197           197
BM_to_string                                                 -0.0004         -0.0004           219           219           219           219
BM_to_chars                                                  +0.0003         +0.0003            42            42            42            42
BM_to_chars_as_string                                        +0.0004         +0.0004            48            48            48            48
BM_format                                                    +0.0016         +0.0016           167           167           167           167
BM_format_to_back_inserter<std::string>                      -0.0128         -0.0127           179           176           179           176
BM_format_to_back_inserter<std::vector<char>>                -0.0216         -0.0216           216           211           216           211
BM_format_to_back_inserter<std::list<char>>                  -0.0008         -0.0008           752           752           752           752
BM_format_to_iterator/<std::array>                           -0.0137         -0.0137           165           162           165           162
BM_format_to_iterator/<std::string>                          -0.0154         -0.0153           165           162           165           162
BM_format_to_iterator/<std::vector>                          -0.0138         -0.0138           165           162           165           162
OVERALL_GEOMEAN                                              -0.0069         -0.0069             0             0             0             0


write_int_comparison:

Before
----------------------------------------------------------------------------------------
Benchmark                                              Time             CPU   Iterations
----------------------------------------------------------------------------------------
BM_sprintf                                          80.3 ns         80.1 ns      8703000
BM_to_string                                        15.0 ns         14.9 ns     46849000
BM_to_chars                                         4.94 ns         4.92 ns    139052000
BM_to_chars_as_string                               15.6 ns         15.6 ns     44945000
BM_format                                           62.1 ns         61.9 ns     11302000
BM_format_to_back_inserter<std::string>             70.3 ns         70.1 ns      9984000
BM_format_to_back_inserter<std::vector<char>>       92.9 ns         92.7 ns      7520000
BM_format_to_back_inserter<std::list<char>>          239 ns          239 ns      2926000
BM_format_to_iterator/<std::array>                  60.6 ns         60.4 ns     11582000
BM_format_to_iterator/<std::string>                 60.2 ns         60.0 ns     11671000
BM_format_to_iterator/<std::vector>                 60.1 ns         60.0 ns     11691000

After
----------------------------------------------------------------------------------------
Benchmark                                              Time             CPU   Iterations
----------------------------------------------------------------------------------------
BM_sprintf                                          81.3 ns         81.2 ns      8546000
BM_to_string                                        14.9 ns         14.9 ns     46809000
BM_to_chars                                         4.93 ns         4.93 ns    138278000
BM_to_chars_as_string                               15.4 ns         15.4 ns     45504000
BM_format                                           62.0 ns         61.9 ns     11330000
BM_format_to_back_inserter<std::string>             69.0 ns         68.9 ns     10164000
BM_format_to_back_inserter<std::vector<char>>       90.4 ns         90.3 ns      7736000
BM_format_to_back_inserter<std::list<char>>          242 ns          242 ns      2891000
BM_format_to_iterator/<std::array>                  58.6 ns         58.6 ns     11952000
BM_format_to_iterator/<std::string>                 58.2 ns         58.1 ns     12052000
BM_format_to_iterator/<std::vector>                 58.4 ns         58.3 ns     11983000

Comparison
Benchmark                                                       Time             CPU      Time Old      Time New       CPU Old       CPU New
--------------------------------------------------------------------------------------------------------------------------------------------
BM_sprintf                                                   +0.0116         +0.0132            80            81            80            81
BM_to_string                                                 -0.0050         -0.0036            15            15            15            15
BM_to_chars                                                  -0.0005         +0.0010             5             5             5             5
BM_to_chars_as_string                                        -0.0168         -0.0149            16            15            16            15
BM_format                                                    -0.0015         +0.0001            62            62            62            62
BM_format_to_back_inserter<std::string>                      -0.0186         -0.0172            70            69            70            69
BM_format_to_back_inserter<std::vector<char>>                -0.0271         -0.0256            93            90            93            90
BM_format_to_back_inserter<std::list<char>>                  +0.0104         +0.0119           239           242           239           242
BM_format_to_iterator/<std::array>                           -0.0322         -0.0304            61            59            60            59
BM_format_to_iterator/<std::string>                          -0.0330         -0.0317            60            58            60            58
BM_format_to_iterator/<std::vector>                          -0.0285         -0.0270            60            58            60            58
OVERALL_GEOMEAN                                              -0.0130         -0.0114             0             0             0             0


write_string_comparison:
Comparison
Benchmark                                                                              Time             CPU      Time Old      Time New       CPU Old       CPU New
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
BM_sprintf/C string len = 6                                                         -0.0037         -0.0051             4             4             4             4
BM_format/C string len = 6                                                          -0.0022         -0.0037            50            49            50            49
BM_format_to_back_inserter<std::string>/C string len = 6                            -0.0136         -0.0151            57            56            57            56
BM_format_to_back_inserter<std::vector<char>>/C string len = 6                      +0.0408         +0.0392            73            76            73            76
BM_format_to_back_inserter<std::deque<char>>/C string len = 6                       +0.0115         +0.0099           156           158           156           157
BM_format_to_back_inserter<std::list<char>>/C string len = 6                        +0.0325         +0.0307           136           140           136           140
BM_format_to_iterator/<std::array> C string len = 6                                 -0.0153         -0.0167            47            46            47            46
BM_format_to_iterator/<std::string> C string len = 6                                -0.0332         -0.0346            47            46            47            46
BM_format_to_iterator/<std::vector> C string len = 6                                -0.0125         -0.0141            46            46            46            46
BM_format_to_iterator/<std::deque> C string len = 6                                 +0.0041         +0.0026            52            53            52            53
BM_format/string len = 6                                                            -0.0170         -0.0185            50            49            50            49
BM_format_to_back_inserter<std::string>/string len = 6                              -0.0092         -0.0106            56            55            56            55
BM_format_to_back_inserter<std::vector<char>>/string len = 6                        +0.0153         +0.0138            73            74            73            74
BM_format_to_back_inserter<std::deque<char>>/string len = 6                         +0.0392         +0.0371           155           161           154           160
BM_format_to_back_inserter<std::list<char>>/string len = 6                          +0.0367         +0.0351           133           138           133           138
BM_format_to_iterator/<std::array> string len = 6                                   -0.0107         -0.0125            47            46            47            46
BM_format_to_iterator/<std::string> string len = 6                                  -0.0312         -0.0326            47            46            47            46
BM_format_to_iterator/<std::vector> string len = 6                                  -0.0103         -0.0144            46            46            46            46
BM_format_to_iterator/<std::deque> string len = 6                                   -0.0042         -0.0057            53            53            53            52
BM_format/string_view len = 6                                                       -0.0191         -0.0206            49            48            49            48
BM_format_to_back_inserter<std::string>/string_view len = 6                         -0.0283         -0.0298            56            55            56            54
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6                   +0.0408         +0.0389            72            75            72            75
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6                    +0.0214         +0.0199           153           157           153           156
BM_format_to_back_inserter<std::list<char>>/string_view len = 6                     +0.0407         +0.0393           132           137           132           137
BM_format_to_iterator/<std::array> string_view len = 6                              -0.0235         -0.0249            46            45            46            45
BM_format_to_iterator/<std::string> string_view len = 6                             -0.0368         -0.0385            46            45            46            44
BM_format_to_iterator/<std::vector> string_view len = 6                             -0.0293         -0.0308            46            45            46            45
BM_format_to_iterator/<std::deque> string_view len = 6                              +0.0094         +0.0079            52            52            52            52
BM_sprintf/C string len = 60                                                        -0.0004         -0.0018             5             5             5             5
BM_format/C string len = 60                                                         +0.0250         +0.0232            64            65            64            65
BM_format_to_back_inserter<std::string>/C string len = 60                           -0.0027         -0.0041            75            75            75            75
BM_format_to_back_inserter<std::vector<char>>/C string len = 60                     +0.0228         +0.0233            89            91            89            91
BM_format_to_back_inserter<std::deque<char>>/C string len = 60                      +0.0303         +0.0312           285           294           285           294
BM_format_to_back_inserter<std::list<char>>/C string len = 60                       +0.0419         +0.0429          1164          1212          1163          1212
BM_format_to_iterator/<std::array> C string len = 60                                -0.0154         -0.0145            46            46            46            46
BM_format_to_iterator/<std::string> C string len = 60                               -0.0355         -0.0345            47            45            47            45
BM_format_to_iterator/<std::vector> C string len = 60                               -0.0161         -0.0152            46            46            46            46
BM_format_to_iterator/<std::deque> C string len = 60                                +0.0044         +0.0054            52            52            52            52
BM_format/string len = 60                                                           +0.0268         +0.0278            62            64            62            64
BM_format_to_back_inserter<std::string>/string len = 60                             -0.0031         -0.0022            75            74            75            74
BM_format_to_back_inserter<std::vector<char>>/string len = 60                       +0.0183         +0.0191            87            88            86            88
BM_format_to_back_inserter<std::deque<char>>/string len = 60                        +0.0567         +0.0578           279           295           279           295
BM_format_to_back_inserter<std::list<char>>/string len = 60                         +0.0386         +0.0396          1167          1212          1165          1212
BM_format_to_iterator/<std::array> string len = 60                                  -0.0094         -0.0084            47            46            47            46
BM_format_to_iterator/<std::string> string len = 60                                 -0.0268         -0.0259            47            46            47            46
BM_format_to_iterator/<std::vector> string len = 60                                 -0.0082         -0.0073            46            46            46            46
BM_format_to_iterator/<std::deque> string len = 60                                  +0.0254         +0.0264            52            54            52            54
BM_format/string_view len = 60                                                      -0.0084         -0.0075            62            62            62            62
BM_format_to_back_inserter<std::string>/string_view len = 60                        -0.0001         +0.0008            74            74            74            74
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60                  +0.0145         +0.0154            86            88            86            88
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60                   +0.0411         +0.0420           279           291           279           291
BM_format_to_back_inserter<std::list<char>>/string_view len = 60                    +0.0358         +0.0368          1164          1205          1163          1205
BM_format_to_iterator/<std::array> string_view len = 60                             -0.0306         -0.0297            47            45            47            45
BM_format_to_iterator/<std::string> string_view len = 60                            -0.0321         -0.0312            46            45            46            45
BM_format_to_iterator/<std::vector> string_view len = 60                            -0.0320         -0.0311            46            45            46            45
BM_format_to_iterator/<std::deque> string_view len = 60                             +0.0039         +0.0048            52            52            52            52
BM_sprintf/C string len = 6000                                                      +0.4788         +0.4802            77           114            77           114
BM_format/C string len = 6000                                                       -0.0087         -0.0078           345           342           345           342
BM_format_to_back_inserter<std::string>/C string len = 6000                         +0.0104         +0.0114          1001          1011          1000          1011
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000                   +0.0195         +0.0206           972           991           971           991
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000                    -0.0092         -0.0082         15129         14990         15114         14990
BM_format_to_back_inserter<std::list<char>>/C string len = 6000                     -0.0017         -0.0007        115290        115092        115167        115090
BM_format_to_iterator/<std::array> C string len = 6000                              -0.0136         -0.0127           161           159           161           159
BM_format_to_iterator/<std::string> C string len = 6000                             -0.0442         -0.0433           154           147           154           147
BM_format_to_iterator/<std::vector> C string len = 6000                             -0.0148         -0.0139           150           148           150           148
BM_format_to_iterator/<std::deque> C string len = 6000                              -0.3357         -0.3350           463           308           463           308
BM_format/string len = 6000                                                         +0.0329         +0.0341           282           291           281           291
BM_format_to_back_inserter<std::string>/string len = 6000                           +0.0289         +0.0299           941           968           940           968
BM_format_to_back_inserter<std::vector<char>>/string len = 6000                     +0.0058         +0.0068           933           938           932           938
BM_format_to_back_inserter<std::deque<char>>/string len = 6000                      -0.0053         -0.0043         15110         15029         15095         15030
BM_format_to_back_inserter<std::list<char>>/string len = 6000                       +0.0041         +0.0065        115131        115601        114854        115597
BM_format_to_iterator/<std::array> string len = 6000                                -0.0028         +0.0000           119           118           118           118
BM_format_to_iterator/<std::string> string len = 6000                               -0.0214         -0.0190           108           105           107           105
BM_format_to_iterator/<std::vector> string len = 6000                               -0.0125         -0.0100           107           105           107           105
BM_format_to_iterator/<std::deque> string len = 6000                                -0.3286         -0.3269           395           265           394           265
BM_format/string_view len = 6000                                                    +0.0084         +0.0110           282           284           281           284
BM_format_to_back_inserter<std::string>/string_view len = 6000                      +0.0347         +0.0373           936           969           934           969
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000                +0.0148         +0.0173           925           938           922           938
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000                 -0.0049         -0.0025         15072         14999         15036         14999
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000                  +0.0017         +0.0040        115332        115524        115059        115520
BM_format_to_iterator/<std::array> string_view len = 6000                           -0.0174         -0.0147           119           117           119           117
BM_format_to_iterator/<std::string> string_view len = 6000                          -0.0269         -0.0245           108           105           107           105
BM_format_to_iterator/<std::vector> string_view len = 6000                          -0.0226         -0.0202           107           105           107           105
BM_format_to_iterator/<std::deque> string_view len = 6000                           -0.3463         -0.3447           392           256           391           256
OVERALL_GEOMEAN                                                                     -0.0089         -0.0087             0             0             0             0


format_to:

Before
--------------------------------------------------------------------------------------------------------------------------
Benchmark                                                                Time             CPU   Iterations UserCounters...
--------------------------------------------------------------------------------------------------------------------------
BM_format_to_string_back_inserter<std::string>/1                      55.3 ns         55.2 ns     12600282 bytes_per_second=17.2841Mi/s
BM_format_to_string_back_inserter<std::string>/2                      55.3 ns         55.2 ns     12711392 bytes_per_second=34.584Mi/s
BM_format_to_string_back_inserter<std::string>/4                      55.3 ns         55.2 ns     12668346 bytes_per_second=69.1337Mi/s
BM_format_to_string_back_inserter<std::string>/8                      55.0 ns         54.8 ns     12806254 bytes_per_second=139.148Mi/s
BM_format_to_string_back_inserter<std::string>/16                     55.0 ns         54.9 ns     12771640 bytes_per_second=278.038Mi/s
BM_format_to_string_back_inserter<std::string>/32                     74.3 ns         74.1 ns      9425332 bytes_per_second=411.691Mi/s
BM_format_to_string_back_inserter<std::string>/64                     74.3 ns         74.1 ns      9467958 bytes_per_second=823.72Mi/s
BM_format_to_string_back_inserter<std::string>/128                    75.6 ns         75.4 ns      9244814 bytes_per_second=1.58012Gi/s
BM_format_to_string_back_inserter<std::string>/256                    90.4 ns         90.1 ns      7758708 bytes_per_second=2.64476Gi/s
BM_format_to_string_back_inserter<std::string>/512                     136 ns          135 ns      5171079 bytes_per_second=3.52016Gi/s
BM_format_to_string_back_inserter<std::string>/1024                    253 ns          252 ns      2766944 bytes_per_second=3.77704Gi/s
BM_format_to_string_back_inserter<std::string>/2048                    410 ns          409 ns      1711155 bytes_per_second=4.66192Gi/s
BM_format_to_string_back_inserter<std::string>/4096                    662 ns          660 ns      1063114 bytes_per_second=5.77795Gi/s
BM_format_to_string_back_inserter<std::string>/8192                   1124 ns         1121 ns       626215 bytes_per_second=6.80694Gi/s
BM_format_to_string_back_inserter<std::string>/16384                  2228 ns         2222 ns       315523 bytes_per_second=6.86706Gi/s
BM_format_to_string_back_inserter<std::string>/32768                  4795 ns         4783 ns       146357 bytes_per_second=6.38068Gi/s
BM_format_to_string_back_inserter<std::string>/65536                  8433 ns         8412 ns        83268 bytes_per_second=7.25532Gi/s
BM_format_to_string_back_inserter<std::string>/131072                44973 ns        44732 ns        15650 bytes_per_second=2.7289Gi/s
BM_format_to_string_back_inserter<std::string>/262144               134871 ns       134517 ns         5205 bytes_per_second=1.81495Gi/s
BM_format_to_string_back_inserter<std::string>/524288               316669 ns       316613 ns         2208 bytes_per_second=1.5422Gi/s
BM_format_to_string_back_inserter<std::string>/1048576              677580 ns       677582 ns         1036 bytes_per_second=1.44125Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/1                69.9 ns         69.9 ns      9994480 bytes_per_second=13.6348Mi/s
BM_format_to_string_back_inserter<std::vector<char>>/2                70.1 ns         70.1 ns      9995724 bytes_per_second=27.2205Mi/s
BM_format_to_string_back_inserter<std::vector<char>>/4                71.3 ns         71.3 ns      9850375 bytes_per_second=53.5283Mi/s
BM_format_to_string_back_inserter<std::vector<char>>/8                73.8 ns         73.8 ns      9486647 bytes_per_second=103.44Mi/s
BM_format_to_string_back_inserter<std::vector<char>>/16               78.7 ns         78.7 ns      8873541 bytes_per_second=193.765Mi/s
BM_format_to_string_back_inserter<std::vector<char>>/32               88.7 ns         88.7 ns      7913676 bytes_per_second=344.039Mi/s
BM_format_to_string_back_inserter<std::vector<char>>/64               90.2 ns         90.2 ns      7740112 bytes_per_second=676.676Mi/s
BM_format_to_string_back_inserter<std::vector<char>>/128              92.2 ns         92.2 ns      7569110 bytes_per_second=1.29352Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/256               106 ns          106 ns      6612544 bytes_per_second=2.25002Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/512               163 ns          163 ns      4299613 bytes_per_second=2.9327Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/1024              240 ns          240 ns      2919691 bytes_per_second=3.98065Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/2048              400 ns          400 ns      1749907 bytes_per_second=4.76489Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/4096              635 ns          635 ns      1101669 bytes_per_second=6.00718Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/8192             1064 ns         1064 ns       655668 bytes_per_second=7.17313Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/16384            1986 ns         1986 ns       352665 bytes_per_second=7.68268Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/32768            3834 ns         3835 ns       182295 bytes_per_second=7.95861Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/65536            7388 ns         7388 ns        94038 bytes_per_second=8.26153Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/131072          17454 ns        17454 ns        40109 bytes_per_second=6.99363Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/262144          36133 ns        36133 ns        19353 bytes_per_second=6.75666Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/524288          73310 ns        73310 ns         9556 bytes_per_second=6.66053Gi/s
BM_format_to_string_back_inserter<std::vector<char>>/1048576        145001 ns       144996 ns         4828 bytes_per_second=6.73509Gi/s
BM_format_to_string_back_inserter<std::list<char>>/1                  62.9 ns         62.9 ns     11119088 bytes_per_second=15.1622Mi/s
BM_format_to_string_back_inserter<std::list<char>>/2                  76.0 ns         76.0 ns      9212976 bytes_per_second=25.0904Mi/s
BM_format_to_string_back_inserter<std::list<char>>/4                   103 ns          103 ns      6740929 bytes_per_second=36.8618Mi/s
BM_format_to_string_back_inserter<std::list<char>>/8                   171 ns          171 ns      4096894 bytes_per_second=44.6147Mi/s
BM_format_to_string_back_inserter<std::list<char>>/16                  324 ns          324 ns      2147006 bytes_per_second=47.0328Mi/s
BM_format_to_string_back_inserter<std::list<char>>/32                  638 ns          638 ns      1096597 bytes_per_second=47.799Mi/s
BM_format_to_string_back_inserter<std::list<char>>/64                 1230 ns         1230 ns       570396 bytes_per_second=49.6318Mi/s
BM_format_to_string_back_inserter<std::list<char>>/128                2427 ns         2427 ns       289550 bytes_per_second=50.306Mi/s
BM_format_to_string_back_inserter<std::list<char>>/256                4847 ns         4847 ns       144614 bytes_per_second=50.3648Mi/s
BM_format_to_string_back_inserter<std::list<char>>/512                9656 ns         9656 ns        72476 bytes_per_second=50.5676Mi/s
BM_format_to_string_back_inserter<std::list<char>>/1024              19415 ns        19416 ns        35934 bytes_per_second=50.298Mi/s
BM_format_to_string_back_inserter<std::list<char>>/2048              38927 ns        38928 ns        17986 bytes_per_second=50.173Mi/s
BM_format_to_string_back_inserter<std::list<char>>/4096              78062 ns        78064 ns         8967 bytes_per_second=50.0392Mi/s
BM_format_to_string_back_inserter<std::list<char>>/8192             156624 ns       156628 ns         4464 bytes_per_second=49.8795Mi/s
BM_format_to_string_back_inserter<std::list<char>>/16384            313781 ns       313788 ns         2232 bytes_per_second=49.7948Mi/s
BM_format_to_string_back_inserter<std::list<char>>/32768            626674 ns       626667 ns         1112 bytes_per_second=49.867Mi/s
BM_format_to_string_back_inserter<std::list<char>>/65536           1248918 ns      1248933 ns          558 bytes_per_second=50.0427Mi/s
BM_format_to_string_back_inserter<std::list<char>>/131072          2512031 ns      2511949 ns          277 bytes_per_second=49.7622Mi/s
BM_format_to_string_back_inserter<std::list<char>>/262144          5118786 ns      5118308 ns          126 bytes_per_second=48.8443Mi/s
BM_format_to_string_back_inserter<std::list<char>>/524288         10395742 ns     10395288 ns           63 bytes_per_second=48.0987Mi/s
BM_format_to_string_back_inserter<std::list<char>>/1048576        21110172 ns     21110073 ns           31 bytes_per_second=47.3708Mi/s
BM_format_to_string_begin<std::string>/1                              47.0 ns         47.0 ns     14928464 bytes_per_second=20.2942Mi/s
BM_format_to_string_begin<std::string>/2                              47.0 ns         47.0 ns     14889677 bytes_per_second=40.5641Mi/s
BM_format_to_string_begin<std::string>/4                              47.1 ns         47.1 ns     14877893 bytes_per_second=81.0735Mi/s
BM_format_to_string_begin<std::string>/8                              47.0 ns         47.0 ns     14855791 bytes_per_second=162.307Mi/s
BM_format_to_string_begin<std::string>/16                             47.1 ns         47.1 ns     14867291 bytes_per_second=324.274Mi/s
BM_format_to_string_begin<std::string>/32                             47.0 ns         47.0 ns     14863938 bytes_per_second=649.013Mi/s
BM_format_to_string_begin<std::string>/64                             46.5 ns         46.5 ns     14004459 bytes_per_second=1.28171Gi/s
BM_format_to_string_begin<std::string>/128                            47.1 ns         47.1 ns     14831108 bytes_per_second=2.53299Gi/s
BM_format_to_string_begin<std::string>/256                            51.6 ns         51.6 ns     13604783 bytes_per_second=4.62228Gi/s
BM_format_to_string_begin<std::string>/512                            50.0 ns         50.0 ns     13980138 bytes_per_second=9.53155Gi/s
BM_format_to_string_begin<std::string>/1024                           59.2 ns         59.2 ns     11872452 bytes_per_second=16.1221Gi/s
BM_format_to_string_begin<std::string>/2048                           69.0 ns         69.0 ns     10128771 bytes_per_second=27.6377Gi/s
BM_format_to_string_begin<std::string>/4096                            100 ns          100 ns      6963452 bytes_per_second=38.0663Gi/s
BM_format_to_string_begin<std::string>/8192                            151 ns          151 ns      4635381 bytes_per_second=50.5416Gi/s
BM_format_to_string_begin<std::string>/16384                           314 ns          314 ns      2233442 bytes_per_second=48.5983Gi/s
BM_format_to_string_begin<std::string>/32768                          1336 ns         1336 ns       524989 bytes_per_second=22.8492Gi/s
BM_format_to_string_begin<std::string>/65536                          3763 ns         3763 ns       185762 bytes_per_second=16.2188Gi/s
BM_format_to_string_begin<std::string>/131072                         6556 ns         6556 ns       106616 bytes_per_second=18.6207Gi/s
BM_format_to_string_begin<std::string>/262144                        13979 ns        13979 ns        50149 bytes_per_second=17.4643Gi/s
BM_format_to_string_begin<std::string>/524288                        28719 ns        28719 ns        24379 bytes_per_second=17.0019Gi/s
BM_format_to_string_begin<std::string>/1048576                       57299 ns        57299 ns        12180 bytes_per_second=17.0432Gi/s
BM_format_to_string_begin<std::vector<char>>/1                        46.1 ns         46.1 ns     15188343 bytes_per_second=20.6809Mi/s
BM_format_to_string_begin<std::vector<char>>/2                        46.1 ns         46.1 ns     15158904 bytes_per_second=41.3318Mi/s
BM_format_to_string_begin<std::vector<char>>/4                        46.1 ns         46.1 ns     15170378 bytes_per_second=82.6776Mi/s
BM_format_to_string_begin<std::vector<char>>/8                        45.7 ns         45.7 ns     15315671 bytes_per_second=167.026Mi/s
BM_format_to_string_begin<std::vector<char>>/16                       46.2 ns         46.2 ns     15163881 bytes_per_second=330.559Mi/s
BM_format_to_string_begin<std::vector<char>>/32                       46.1 ns         46.1 ns     15201091 bytes_per_second=661.98Mi/s
BM_format_to_string_begin<std::vector<char>>/64                       46.2 ns         46.2 ns     14183997 bytes_per_second=1.28927Gi/s
BM_format_to_string_begin<std::vector<char>>/128                      46.7 ns         46.7 ns     14987395 bytes_per_second=2.55007Gi/s
BM_format_to_string_begin<std::vector<char>>/256                      51.3 ns         51.3 ns     13898949 bytes_per_second=4.64462Gi/s
BM_format_to_string_begin<std::vector<char>>/512                      50.1 ns         50.1 ns     10000000 bytes_per_second=9.52165Gi/s
BM_format_to_string_begin<std::vector<char>>/1024                     59.2 ns         59.2 ns     11805042 bytes_per_second=16.105Gi/s
BM_format_to_string_begin<std::vector<char>>/2048                     69.0 ns         69.0 ns     10139614 bytes_per_second=27.6266Gi/s
BM_format_to_string_begin<std::vector<char>>/4096                     97.6 ns         97.6 ns      7179535 bytes_per_second=39.0938Gi/s
BM_format_to_string_begin<std::vector<char>>/8192                      152 ns          152 ns      4610486 bytes_per_second=50.227Gi/s
BM_format_to_string_begin<std::vector<char>>/16384                     314 ns          314 ns      2230251 bytes_per_second=48.5946Gi/s
BM_format_to_string_begin<std::vector<char>>/32768                    1333 ns         1333 ns       525550 bytes_per_second=22.8868Gi/s
BM_format_to_string_begin<std::vector<char>>/65536                    3760 ns         3760 ns       185821 bytes_per_second=16.2322Gi/s
BM_format_to_string_begin<std::vector<char>>/131072                   6479 ns         6480 ns       107960 bytes_per_second=18.8391Gi/s
BM_format_to_string_begin<std::vector<char>>/262144                  14164 ns        14164 ns        49862 bytes_per_second=17.2368Gi/s
BM_format_to_string_begin<std::vector<char>>/524288                  28916 ns        28916 ns        24149 bytes_per_second=16.8861Gi/s
BM_format_to_string_begin<std::vector<char>>/1048576                 57621 ns        57622 ns        12140 bytes_per_second=16.9478Gi/s
BM_format_to_string_begin<std::list<char>>/1                          47.6 ns         47.6 ns     14675857 bytes_per_second=20.0271Mi/s
BM_format_to_string_begin<std::list<char>>/2                          48.8 ns         48.8 ns     14331930 bytes_per_second=39.1155Mi/s
BM_format_to_string_begin<std::list<char>>/4                          50.9 ns         50.9 ns     13747606 bytes_per_second=74.9309Mi/s
BM_format_to_string_begin<std::list<char>>/8                          63.4 ns         63.4 ns     11065440 bytes_per_second=120.329Mi/s
BM_format_to_string_begin<std::list<char>>/16                         82.4 ns         82.4 ns      8510480 bytes_per_second=185.222Mi/s
BM_format_to_string_begin<std::list<char>>/32                          126 ns          126 ns      5564932 bytes_per_second=242.653Mi/s
BM_format_to_string_begin<std::list<char>>/64                          211 ns          211 ns      3311820 bytes_per_second=289.214Mi/s
BM_format_to_string_begin<std::list<char>>/128                         384 ns          384 ns      1825012 bytes_per_second=318.238Mi/s
BM_format_to_string_begin<std::list<char>>/256                         735 ns          735 ns       951285 bytes_per_second=332.108Mi/s
BM_format_to_string_begin<std::list<char>>/512                        1428 ns         1428 ns       489437 bytes_per_second=341.969Mi/s
BM_format_to_string_begin<std::list<char>>/1024                       2792 ns         2792 ns       242406 bytes_per_second=349.822Mi/s
BM_format_to_string_begin<std::list<char>>/2048                       5594 ns         5594 ns       124188 bytes_per_second=349.129Mi/s
BM_format_to_string_begin<std::list<char>>/4096                      11163 ns        11163 ns        62794 bytes_per_second=349.936Mi/s
BM_format_to_string_begin<std::list<char>>/8192                      22339 ns        22339 ns        31335 bytes_per_second=349.718Mi/s
BM_format_to_string_begin<std::list<char>>/16384                     44673 ns        44674 ns        15675 bytes_per_second=349.754Mi/s
BM_format_to_string_begin<std::list<char>>/32768                     89015 ns        89016 ns         7849 bytes_per_second=351.06Mi/s
BM_format_to_string_begin<std::list<char>>/65536                    177988 ns       177989 ns         3938 bytes_per_second=351.145Mi/s
BM_format_to_string_begin<std::list<char>>/131072                   362715 ns       362697 ns         1933 bytes_per_second=344.64Mi/s
BM_format_to_string_begin<std::list<char>>/262144                   846730 ns       846685 ns          825 bytes_per_second=295.269Mi/s
BM_format_to_string_begin<std::list<char>>/524288                  2018755 ns      2018721 ns          347 bytes_per_second=247.682Mi/s
BM_format_to_string_begin<std::list<char>>/1048576                 4225251 ns      4225188 ns          165 bytes_per_second=236.676Mi/s
BM_format_to_string_span<char>/1                                      46.2 ns         46.2 ns     15156896 bytes_per_second=20.6258Mi/s
BM_format_to_string_span<char>/2                                      46.3 ns         46.3 ns     15114242 bytes_per_second=41.1559Mi/s
BM_format_to_string_span<char>/4                                      46.4 ns         46.4 ns     15089475 bytes_per_second=82.1686Mi/s
BM_format_to_string_span<char>/8                                      45.9 ns         45.9 ns     15249334 bytes_per_second=166.143Mi/s
BM_format_to_string_span<char>/16                                     46.3 ns         46.3 ns     15087074 bytes_per_second=329.233Mi/s
BM_format_to_string_span<char>/32                                     46.4 ns         46.4 ns     15099464 bytes_per_second=657.611Mi/s
BM_format_to_string_span<char>/64                                     46.4 ns         46.4 ns     14101746 bytes_per_second=1.2849Gi/s
BM_format_to_string_span<char>/128                                    47.0 ns         47.0 ns     14919410 bytes_per_second=2.53769Gi/s
BM_format_to_string_span<char>/256                                    50.8 ns         50.8 ns     13874090 bytes_per_second=4.69274Gi/s
BM_format_to_string_span<char>/512                                    50.5 ns         50.5 ns     13849265 bytes_per_second=9.44604Gi/s
BM_format_to_string_span<char>/1024                                   59.6 ns         59.6 ns     11774716 bytes_per_second=16.008Gi/s
BM_format_to_string_span<char>/2048                                   69.3 ns         69.3 ns     10102354 bytes_per_second=27.5137Gi/s
BM_format_to_string_span<char>/4096                                   98.0 ns         98.0 ns      7137947 bytes_per_second=38.9144Gi/s
BM_format_to_string_span<char>/8192                                    153 ns          153 ns      4585057 bytes_per_second=49.9901Gi/s
BM_format_to_string_span<char>/16384                                   316 ns          316 ns      2225896 bytes_per_second=48.3398Gi/s
BM_format_to_string_span<char>/32768                                  1339 ns         1339 ns       520365 bytes_per_second=22.7872Gi/s
BM_format_to_string_span<char>/65536                                  3780 ns         3780 ns       184720 bytes_per_second=16.1474Gi/s
BM_format_to_string_span<char>/131072                                 6557 ns         6557 ns       106444 bytes_per_second=18.6157Gi/s
BM_format_to_string_span<char>/262144                                14199 ns        14199 ns        49363 bytes_per_second=17.1939Gi/s
BM_format_to_string_span<char>/524288                                28833 ns        28834 ns        24254 bytes_per_second=16.9343Gi/s
BM_format_to_string_span<char>/1048576                               57660 ns        57660 ns        12166 bytes_per_second=16.9365Gi/s
BM_format_to_string_pointer<char>/1                                   46.4 ns         46.4 ns     15070582 bytes_per_second=20.5355Mi/s
BM_format_to_string_pointer<char>/2                                   46.5 ns         46.5 ns     15064611 bytes_per_second=41.0239Mi/s
BM_format_to_string_pointer<char>/4                                   46.4 ns         46.4 ns     15080092 bytes_per_second=82.1674Mi/s
BM_format_to_string_pointer<char>/8                                   45.9 ns         45.9 ns     15239465 bytes_per_second=166.094Mi/s
BM_format_to_string_pointer<char>/16                                  46.4 ns         46.4 ns     15077440 bytes_per_second=328.884Mi/s
BM_format_to_string_pointer<char>/32                                  46.4 ns         46.4 ns     15070278 bytes_per_second=657.438Mi/s
BM_format_to_string_pointer<char>/64                                  46.4 ns         46.4 ns     14094814 bytes_per_second=1.28358Gi/s
BM_format_to_string_pointer<char>/128                                 46.8 ns         46.8 ns     14894522 bytes_per_second=2.54466Gi/s
BM_format_to_string_pointer<char>/256                                 51.2 ns         51.2 ns     13908865 bytes_per_second=4.65713Gi/s
BM_format_to_string_pointer<char>/512                                 50.2 ns         50.2 ns     13999036 bytes_per_second=9.5049Gi/s
BM_format_to_string_pointer<char>/1024                                59.4 ns         59.4 ns     11805502 bytes_per_second=16.0611Gi/s
BM_format_to_string_pointer<char>/2048                                69.1 ns         69.1 ns     10114415 bytes_per_second=27.5936Gi/s
BM_format_to_string_pointer<char>/4096                                97.6 ns         97.6 ns      7154104 bytes_per_second=39.0914Gi/s
BM_format_to_string_pointer<char>/8192                                 151 ns          151 ns      4653492 bytes_per_second=50.6101Gi/s
BM_format_to_string_pointer<char>/16384                                314 ns          314 ns      2222259 bytes_per_second=48.6129Gi/s
BM_format_to_string_pointer<char>/32768                               1336 ns         13…

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


2 Files Affected:

- (modified) libcxx/include/__format/buffer.h (+90) 
- (modified) libcxx/include/__format/format_functions.h (+2-2) 


``````````diff
diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h
index bfe26bfb01cb5..5337c2fe0481c 100644
--- a/libcxx/include/__format/buffer.h
+++ b/libcxx/include/__format/buffer.h
@@ -39,6 +39,7 @@
 #include <__utility/exception_guard.h>
 #include <__utility/move.h>
 #include <cstddef>
+#include <stdexcept>
 #include <string_view>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -722,6 +723,95 @@ class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT>
   }
 };
 
+// A buffer that directly writes to the underlying buffer.
+template <class _OutIt, __fmt_char_type _CharT>
+class _LIBCPP_TEMPLATE_VIS __direct_iterator_buffer : public __output_buffer<_CharT> {
+public:
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it)
+      : __output_buffer<_CharT>{std::__unwrap_iter(__out_it), __buffer_size, __prepare_write}, __out_it_(__out_it) {}
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return __out_it_ + this->__size(); }
+
+private:
+  // The function format_to expects a buffer large enough for the output. The
+  // function format_to_n has its own helper class that restricts the number of
+  // write options. So this function class can pretend to have an infinite
+  // buffer.
+  static constexpr size_t __buffer_size = -1;
+
+  _OutIt __out_it_;
+
+  _LIBCPP_HIDE_FROM_ABI static void
+  __prepare_write([[maybe_unused]] __output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) {
+    std::__throw_length_error("__direct_iterator_buffer");
+  }
+};
+
+// A buffer that writes its output to the end of a container.
+template <class _OutIt, __fmt_char_type _CharT>
+class _LIBCPP_TEMPLATE_VIS __container_inserter_buffer : public __output_buffer<_CharT> {
+public:
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it)
+      : __output_buffer<_CharT>{__buffer_, __buffer_size, __prepare_write}, __container_{__out_it.__get_container()} {}
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && {
+    __container_->insert(__container_->end(), __buffer_, __buffer_ + this->__size());
+    return std::back_inserter(*__container_);
+  }
+
+private:
+  typename __back_insert_iterator_container<_OutIt>::type* __container_;
+
+  // This class uses a fixed size buffer and appends the elements in
+  // __buffer_size chunks. An alternative would be to use an allocating buffer
+  // and append the output in one write operation. Benchmarking showed no
+  // performance difference.
+  static constexpr size_t __buffer_size = 256;
+  _CharT __buffer_[__buffer_size];
+
+  _LIBCPP_HIDE_FROM_ABI void __prepare_write() {
+    __container_->insert(__container_->end(), __buffer_, __buffer_ + this->__size());
+    this->__buffer_flused();
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static void
+  __prepare_write(__output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) {
+    static_cast<__container_inserter_buffer<_OutIt, _CharT>&>(__buffer).__prepare_write();
+  }
+};
+
+// A buffer that writes to an iterator.
+//
+// Unlinke the __container_inserter_buffer this class' perfomance does benefit
+// from allocating and then inserting.
+template <class _OutIt, __fmt_char_type _CharT>
+class _LIBCPP_TEMPLATE_VIS __iterator_buffer : public __allocating_buffer<_CharT> {
+public:
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it)
+      : __allocating_buffer<_CharT>{}, __out_it_{std::move(__out_it)} {}
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && {
+    return std::ranges::copy(this->__view(), std::move(__out_it_)).out;
+  }
+
+private:
+  _OutIt __out_it_;
+};
+
+// Selects the type of the buffer used for the output iterator.
+template <class _OutIt, __fmt_char_type _CharT>
+class _LIBCPP_TEMPLATE_VIS __buffer_selector {
+  using _Container = __back_insert_iterator_container<_OutIt>::type;
+
+public:
+  using type =
+      conditional_t<!same_as<_Container, void>,
+                    __container_inserter_buffer<_OutIt, _CharT>,
+                    conditional_t<__enable_direct_output<_OutIt, _CharT>,
+                                  __direct_iterator_buffer<_OutIt, _CharT>,
+                                  __iterator_buffer<_OutIt, _CharT>>>;
+};
+
 // ***** ***** ***** LLVM-19 and LLVM-20 class ***** ***** *****
 
 // A dynamically growing buffer intended to be used for retargeting a context.
diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h
index a5c63bd4db70f..523cd5a785a9b 100644
--- a/libcxx/include/__format/format_functions.h
+++ b/libcxx/include/__format/format_functions.h
@@ -411,7 +411,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(_OutIt __out_it,
     return std::__format::__vformat_to(
         basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(std::move(__out_it), __args));
   else {
-    __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)};
+    typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)};
     std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
                                 std::__format_context_create(__buffer.__make_output_iterator(), __args));
     return std::move(__buffer).__out_it();
@@ -544,7 +544,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(
     return std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
                                        std::__format_context_create(std::move(__out_it), __args, std::move(__loc)));
   else {
-    __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)};
+    typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)};
     std::__format::__vformat_to(
         basic_format_parse_context{__fmt, __args.__size()},
         std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));

``````````

</details>


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


More information about the llvm-branch-commits mailing list