Skip to content

Conversation

mordante
Copy link
Member

@mordante mordante commented Aug 3, 2024

This changes the __output_buffer to a new structure. Since the other formatting functions std::format_to, std::format_to_n, and std::formatted_size still use the old codepaths the class is in a transition state. At the end of the patch series the class should be in its final state.

write_double_comparison:

Before

Benchmark Time CPU Iterations

BM_sprintf 197 ns 196 ns 3550000
BM_to_string 218 ns 218 ns 3214000
BM_to_chars 42.4 ns 42.3 ns 16575000
BM_to_chars_as_string 48.2 ns 48.1 ns 14542000
BM_format 175 ns 175 ns 4000000
BM_format_to_back_inserterstd::string 175 ns 175 ns 3995000
BM_format_to_back_inserter<std::vector> 207 ns 206 ns 3393000
BM_format_to_back_inserter<std::list> 752 ns 750 ns 931000
BM_format_to_iterator/std::array 161 ns 161 ns 4345000
BM_format_to_iterator/std::string 161 ns 161 ns 4344000
BM_format_to_iterator/std::vector 162 ns 161 ns 4344000

After

Benchmark Time CPU Iterations

BM_sprintf 197 ns 197 ns 3550000
BM_to_string 219 ns 219 ns 3199000
BM_to_chars 42.4 ns 42.4 ns 16554000
BM_to_chars_as_string 48.1 ns 48.1 ns 14569000
BM_format 167 ns 167 ns 4203000
BM_format_to_back_inserterstd::string 179 ns 179 ns 3920000
BM_format_to_back_inserter<std::vector> 214 ns 214 ns 3274000
BM_format_to_back_inserter<std::list> 751 ns 751 ns 930000
BM_format_to_iterator/std::array 164 ns 164 ns 4258000
BM_format_to_iterator/std::string 165 ns 164 ns 4247000
BM_format_to_iterator/std::vector 165 ns 165 ns 4248000

Comparison
Benchmark Time CPU Time Old Time New CPU Old CPU New

BM_sprintf +0.0013 +0.0028 197 197 196 197
BM_to_string +0.0023 +0.0038 218 219 218 219
BM_to_chars +0.0014 +0.0030 42 42 42 42
BM_to_chars_as_string -0.0025 -0.0010 48 48 48 48
BM_format -0.0476 -0.0462 175 167 175 167
BM_format_to_back_inserterstd::string +0.0190 +0.0205 175 179 175 179
BM_format_to_back_inserter<std::vector> +0.0348 +0.0363 207 214 206 214
BM_format_to_back_inserter<std::list> -0.0013 +0.0005 752 751 750 751
BM_format_to_iterator/std::array +0.0188 +0.0203 161 164 161 164
BM_format_to_iterator/std::string +0.0207 +0.0226 161 165 161 164
BM_format_to_iterator/std::vector +0.0197 +0.0212 162 165 161 165
OVERALL_GEOMEAN +0.0058 +0.0074 0 0 0 0

write_int_comparison:

Before

Benchmark Time CPU Iterations

BM_sprintf 79.6 ns 79.5 ns 8739000
BM_to_string 14.9 ns 14.9 ns 46713000
BM_to_chars 5.68 ns 5.67 ns 120614000
BM_to_chars_as_string 14.2 ns 14.1 ns 49513000
BM_format 69.3 ns 69.2 ns 10105000
BM_format_to_back_inserterstd::string 69.2 ns 69.1 ns 10138000
BM_format_to_back_inserter<std::vector> 90.6 ns 90.5 ns 7728000
BM_format_to_back_inserter<std::list> 234 ns 234 ns 2986000
BM_format_to_iterator/std::array 59.3 ns 59.3 ns 11805000
BM_format_to_iterator/std::string 58.7 ns 58.6 ns 11943000
BM_format_to_iterator/std::vector 60.1 ns 60.1 ns 11670000

After

Benchmark Time CPU Iterations

BM_sprintf 80.2 ns 80.2 ns 8670000
BM_to_string 15.0 ns 15.0 ns 46559000
BM_to_chars 4.93 ns 4.93 ns 138016000
BM_to_chars_as_string 15.4 ns 15.4 ns 45415000
BM_format 62.1 ns 62.0 ns 11316000
BM_format_to_back_inserterstd::string 70.2 ns 70.2 ns 9962000
BM_format_to_back_inserter<std::vector> 92.8 ns 92.8 ns 7544000
BM_format_to_back_inserter<std::list> 240 ns 240 ns 2917000
BM_format_to_iterator/std::array 60.5 ns 60.5 ns 11572000
BM_format_to_iterator/std::string 60.2 ns 60.2 ns 11653000
BM_format_to_iterator/std::vector 60.1 ns 60.1 ns 11659000

Comparison
Benchmark Time CPU Time Old Time New CPU Old CPU New

BM_sprintf +0.0072 +0.0081 80 80 80 80
BM_to_string +0.0043 +0.0053 15 15 15 15
BM_to_chars -0.1324 -0.1316 6 5 6 5
BM_to_chars_as_string +0.0895 +0.0906 14 15 14 15
BM_format -0.1047 -0.1040 69 62 69 62
BM_format_to_back_inserterstd::string +0.0148 +0.0157 69 70 69 70
BM_format_to_back_inserter<std::vector> +0.0241 +0.0251 91 93 90 93
BM_format_to_back_inserter<std::list> +0.0222 +0.0232 234 240 234 240
BM_format_to_iterator/std::array +0.0196 +0.0205 59 60 59 60
BM_format_to_iterator/std::string +0.0266 +0.0275 59 60 59 60
BM_format_to_iterator/std::vector -0.0004 +0.0005 60 60 60 60
OVERALL_GEOMEAN -0.0045 -0.0036 0 0 0 0

write_string_comparison:

Before

Benchmark Time CPU Iterations

BM_sprintf/C string len = 6 4.82 ns 4.82 ns 145548481
BM_format/C string len = 6 55.1 ns 55.1 ns 12713693
BM_format_to_back_inserterstd::string/C string len = 6 55.1 ns 55.1 ns 12690821
BM_format_to_back_inserter<std::vector>/C string len = 6 71.5 ns 71.5 ns 9805550
BM_format_to_back_inserter<std::deque>/C string len = 6 154 ns 154 ns 4536256
BM_format_to_back_inserter<std::list>/C string len = 6 130 ns 130 ns 5348845
BM_format_to_iterator/std::array C string len = 6 44.9 ns 44.9 ns 15556175
BM_format_to_iterator/std::string C string len = 6 45.8 ns 45.8 ns 15290662
BM_format_to_iterator/std::vector C string len = 6 44.4 ns 44.4 ns 15807704
BM_format_to_iterator/std::deque C string len = 6 50.0 ns 50.0 ns 13973893
BM_format/string len = 6 54.7 ns 54.7 ns 12793406
BM_format_to_back_inserterstd::string/string len = 6 55.5 ns 55.5 ns 12620370
BM_format_to_back_inserter<std::vector>/string len = 6 70.4 ns 70.4 ns 9936490
BM_format_to_back_inserter<std::deque>/string len = 6 155 ns 155 ns 4521357
BM_format_to_back_inserter<std::list>/string len = 6 135 ns 135 ns 5201519
BM_format_to_iterator/std::array string len = 6 44.6 ns 44.6 ns 15703872
BM_format_to_iterator/std::string string len = 6 45.0 ns 45.0 ns 15545182
BM_format_to_iterator/std::vector string len = 6 45.0 ns 45.0 ns 15539130
BM_format_to_iterator/std::deque string len = 6 50.5 ns 50.5 ns 13846916
BM_format/string_view len = 6 54.6 ns 54.6 ns 12821301
BM_format_to_back_inserterstd::string/string_view len = 6 54.6 ns 54.6 ns 12827673
BM_format_to_back_inserter<std::vector>/string_view len = 6 69.9 ns 69.9 ns 9958365
BM_format_to_back_inserter<std::deque>/string_view len = 6 157 ns 157 ns 4462445
BM_format_to_back_inserter<std::list>/string_view len = 6 134 ns 134 ns 5232155
BM_format_to_iterator/std::array string_view len = 6 44.2 ns 44.2 ns 15871362
BM_format_to_iterator/std::string string_view len = 6 45.0 ns 45.0 ns 15582582
BM_format_to_iterator/std::vector string_view len = 6 45.1 ns 45.1 ns 15539906
BM_format_to_iterator/std::deque string_view len = 6 50.5 ns 50.5 ns 13896524
BM_sprintf/C string len = 60 4.15 ns 4.15 ns 168165776
BM_format/C string len = 60 73.8 ns 73.8 ns 9498291
BM_format_to_back_inserterstd::string/C string len = 60 73.6 ns 73.6 ns 9535890
BM_format_to_back_inserter<std::vector>/C string len = 60 83.1 ns 83.1 ns 8428154
BM_format_to_back_inserter<std::deque>/C string len = 60 281 ns 281 ns 2490093
BM_format_to_back_inserter<std::list>/C string len = 60 1157 ns 1157 ns 605227
BM_format_to_iterator/std::array C string len = 60 44.9 ns 44.9 ns 15604442
BM_format_to_iterator/std::string C string len = 60 45.8 ns 45.8 ns 15272196
BM_format_to_iterator/std::vector C string len = 60 44.6 ns 44.7 ns 15683193
BM_format_to_iterator/std::deque C string len = 60 50.6 ns 50.6 ns 13698382
BM_format/string len = 60 72.3 ns 72.3 ns 9648955
BM_format_to_back_inserterstd::string/string len = 60 72.0 ns 72.0 ns 9738373
BM_format_to_back_inserter<std::vector>/string len = 60 82.3 ns 82.3 ns 8517896
BM_format_to_back_inserter<std::deque>/string len = 60 280 ns 280 ns 2496054
BM_format_to_back_inserter<std::list>/string len = 60 1162 ns 1162 ns 602383
BM_format_to_iterator/std::array string len = 60 44.5 ns 44.5 ns 15727799
BM_format_to_iterator/std::string string len = 60 49.6 ns 49.6 ns 14096012
BM_format_to_iterator/std::vector string len = 60 49.8 ns 49.8 ns 14053734
BM_format_to_iterator/std::deque string len = 60 50.8 ns 50.8 ns 13801448
BM_format/string_view len = 60 72.5 ns 72.5 ns 9653638
BM_format_to_back_inserterstd::string/string_view len = 60 72.7 ns 72.7 ns 9598203
BM_format_to_back_inserter<std::vector>/string_view len = 60 81.9 ns 81.9 ns 8522306
BM_format_to_back_inserter<std::deque>/string_view len = 60 283 ns 283 ns 2475014
BM_format_to_back_inserter<std::list>/string_view len = 60 1162 ns 1162 ns 600924
BM_format_to_iterator/std::array string_view len = 60 44.1 ns 44.1 ns 15858951
BM_format_to_iterator/std::string string_view len = 60 44.9 ns 44.9 ns 15579340
BM_format_to_iterator/std::vector string_view len = 60 44.9 ns 44.9 ns 15586711
BM_format_to_iterator/std::deque string_view len = 60 50.0 ns 50.0 ns 13980804
BM_sprintf/C string len = 6000 116 ns 116 ns 6051541
BM_format/C string len = 6000 1000 ns 1000 ns 698647
BM_format_to_back_inserterstd::string/C string len = 6000 1002 ns 1002 ns 701440
BM_format_to_back_inserter<std::vector>/C string len = 6000 956 ns 956 ns 727585
BM_format_to_back_inserter<std::deque>/C string len = 6000 14898 ns 14898 ns 46994
BM_format_to_back_inserter<std::list>/C string len = 6000 114860 ns 114859 ns 6106
BM_format_to_iterator/std::array C string len = 6000 158 ns 158 ns 4425133
BM_format_to_iterator/std::string C string len = 6000 161 ns 161 ns 4335471
BM_format_to_iterator/std::vector C string len = 6000 157 ns 157 ns 4444174
BM_format_to_iterator/std::deque C string len = 6000 445 ns 445 ns 1574120
BM_format/string len = 6000 929 ns 929 ns 753630
BM_format_to_back_inserterstd::string/string len = 6000 930 ns 930 ns 752888
BM_format_to_back_inserter<std::vector>/string len = 6000 910 ns 910 ns 771111
BM_format_to_back_inserter<std::deque>/string len = 6000 14875 ns 14876 ns 47221
BM_format_to_back_inserter<std::list>/string len = 6000 114937 ns 114936 ns 6092
BM_format_to_iterator/std::array string len = 6000 118 ns 118 ns 5963643
BM_format_to_iterator/std::string string len = 6000 106 ns 106 ns 6584711
BM_format_to_iterator/std::vector string len = 6000 106 ns 106 ns 6583118
BM_format_to_iterator/std::deque string len = 6000 391 ns 391 ns 1790538
BM_format/string_view len = 6000 935 ns 935 ns 744348
BM_format_to_back_inserterstd::string/string_view len = 6000 934 ns 934 ns 742039
BM_format_to_back_inserter<std::vector>/string_view len = 6000 895 ns 895 ns 783527
BM_format_to_back_inserter<std::deque>/string_view len = 6000 14864 ns 14865 ns 47122
BM_format_to_back_inserter<std::list>/string_view len = 6000 115042 ns 115044 ns 6091
BM_format_to_iterator/std::array string_view len = 6000 115 ns 115 ns 6070197
BM_format_to_iterator/std::string string_view len = 6000 116 ns 116 ns 6035109
BM_format_to_iterator/std::vector string_view len = 6000 115 ns 115 ns 6067683
BM_format_to_iterator/std::deque string_view len = 6000 387 ns 387 ns 1803466

After

Benchmark Time CPU Iterations

BM_sprintf/C string len = 6 3.56 ns 3.56 ns 196337806
BM_format/C string len = 6 49.1 ns 49.1 ns 14241174
BM_format_to_back_inserterstd::string/C string len = 6 56.8 ns 56.8 ns 12341483
BM_format_to_back_inserter<std::vector>/C string len = 6 72.9 ns 72.9 ns 9610864
BM_format_to_back_inserter<std::deque>/C string len = 6 155 ns 155 ns 4528719
BM_format_to_back_inserter<std::list>/C string len = 6 137 ns 137 ns 5103340
BM_format_to_iterator/std::array C string len = 6 46.4 ns 46.4 ns 15081626
BM_format_to_iterator/std::string C string len = 6 47.0 ns 47.0 ns 14893458
BM_format_to_iterator/std::vector C string len = 6 45.9 ns 45.9 ns 15243762
BM_format_to_iterator/std::deque C string len = 6 52.6 ns 52.6 ns 13323560
BM_format/string len = 6 49.3 ns 49.3 ns 14181485
BM_format_to_back_inserterstd::string/string len = 6 55.4 ns 55.4 ns 12644078
BM_format_to_back_inserter<std::vector>/string len = 6 72.7 ns 72.7 ns 9618696
BM_format_to_back_inserter<std::deque>/string len = 6 154 ns 154 ns 4540873
BM_format_to_back_inserter<std::list>/string len = 6 134 ns 134 ns 5220153
BM_format_to_iterator/std::array string len = 6 46.5 ns 46.5 ns 15064445
BM_format_to_iterator/std::string string len = 6 47.3 ns 47.3 ns 14786851
BM_format_to_iterator/std::vector string len = 6 46.5 ns 46.5 ns 15069381
BM_format_to_iterator/std::deque string len = 6 52.9 ns 52.9 ns 13207437
BM_format/string_view len = 6 47.6 ns 47.6 ns 14688449
BM_format_to_back_inserterstd::string/string_view len = 6 56.1 ns 56.1 ns 12514239
BM_format_to_back_inserter<std::vector>/string_view len = 6 72.0 ns 72.0 ns 9705591
BM_format_to_back_inserter<std::deque>/string_view len = 6 152 ns 152 ns 4607470
BM_format_to_back_inserter<std::list>/string_view len = 6 134 ns 134 ns 5233005
BM_format_to_iterator/std::array string_view len = 6 46.0 ns 46.0 ns 15205542
BM_format_to_iterator/std::string string_view len = 6 46.5 ns 46.5 ns 15067775
BM_format_to_iterator/std::vector string_view len = 6 46.5 ns 46.5 ns 15057288
BM_format_to_iterator/std::deque string_view len = 6 51.8 ns 51.8 ns 13564649
BM_sprintf/C string len = 60 4.83 ns 4.83 ns 145020116
BM_format/C string len = 60 72.3 ns 72.3 ns 9665555
BM_format_to_back_inserterstd::string/C string len = 60 85.0 ns 85.0 ns 8249050
BM_format_to_back_inserter<std::vector>/C string len = 60 94.7 ns 94.7 ns 7398143
BM_format_to_back_inserter<std::deque>/C string len = 60 286 ns 286 ns 2452225
BM_format_to_back_inserter<std::list>/C string len = 60 1179 ns 1179 ns 595011
BM_format_to_iterator/std::array C string len = 60 46.1 ns 46.1 ns 15157525
BM_format_to_iterator/std::string C string len = 60 47.0 ns 47.0 ns 14899863
BM_format_to_iterator/std::vector C string len = 60 45.8 ns 45.8 ns 15272542
BM_format_to_iterator/std::deque C string len = 60 58.7 ns 58.7 ns 11958910
BM_format/string len = 60 61.7 ns 61.7 ns 11308865
BM_format_to_back_inserterstd::string/string len = 60 74.2 ns 74.2 ns 9401855
BM_format_to_back_inserter<std::vector>/string len = 60 86.6 ns 86.6 ns 8079197
BM_format_to_back_inserter<std::deque>/string len = 60 278 ns 278 ns 2519254
BM_format_to_back_inserter<std::list>/string len = 60 1169 ns 1170 ns 597703
BM_format_to_iterator/std::array string len = 60 46.4 ns 46.4 ns 15074759
BM_format_to_iterator/std::string string len = 60 47.3 ns 47.3 ns 14801107
BM_format_to_iterator/std::vector string len = 60 46.3 ns 46.4 ns 15085548
BM_format_to_iterator/std::deque string len = 60 52.2 ns 52.2 ns 13331015
BM_format/string_view len = 60 65.0 ns 65.0 ns 10756847
BM_format_to_back_inserterstd::string/string_view len = 60 78.5 ns 78.5 ns 9051370
BM_format_to_back_inserter<std::vector>/string_view len = 60 87.9 ns 87.9 ns 7946825
BM_format_to_back_inserter<std::deque>/string_view len = 60 280 ns 280 ns 2505999
BM_format_to_back_inserter<std::list>/string_view len = 60 1174 ns 1174 ns 594829
BM_format_to_iterator/std::array string_view len = 60 46.3 ns 46.3 ns 15149785
BM_format_to_iterator/std::string string_view len = 60 46.7 ns 46.7 ns 15002678
BM_format_to_iterator/std::vector string_view len = 60 46.7 ns 46.7 ns 14996445
BM_format_to_iterator/std::deque string_view len = 60 52.6 ns 52.6 ns 13255470
BM_sprintf/C string len = 6000 77.1 ns 77.1 ns 9099121
BM_format/C string len = 6000 350 ns 350 ns 2013049
BM_format_to_back_inserterstd::string/C string len = 6000 992 ns 992 ns 709093
BM_format_to_back_inserter<std::vector>/C string len = 6000 1016 ns 1016 ns 694784
BM_format_to_back_inserter<std::deque>/C string len = 6000 15158 ns 15159 ns 46125
BM_format_to_back_inserter<std::list>/C string len = 6000 115703 ns 115705 ns 6055
BM_format_to_iterator/std::array C string len = 6000 166 ns 166 ns 4224749
BM_format_to_iterator/std::string C string len = 6000 153 ns 153 ns 4573034
BM_format_to_iterator/std::vector C string len = 6000 150 ns 150 ns 4678898
BM_format_to_iterator/std::deque C string len = 6000 465 ns 465 ns 1506323
BM_format/string len = 6000 281 ns 281 ns 2462572
BM_format_to_back_inserterstd::string/string len = 6000 935 ns 935 ns 745376
BM_format_to_back_inserter<std::vector>/string len = 6000 939 ns 939 ns 747498
BM_format_to_back_inserter<std::deque>/string len = 6000 15069 ns 15069 ns 46429
BM_format_to_back_inserter<std::list>/string len = 6000 115537 ns 115539 ns 6063
BM_format_to_iterator/std::array string len = 6000 120 ns 120 ns 5849159
BM_format_to_iterator/std::string string len = 6000 108 ns 108 ns 6482306
BM_format_to_iterator/std::vector string len = 6000 107 ns 107 ns 6547915
BM_format_to_iterator/std::deque string len = 6000 397 ns 397 ns 1763729
BM_format/string_view len = 6000 282 ns 282 ns 2490133
BM_format_to_back_inserterstd::string/string_view len = 6000 927 ns 927 ns 750931
BM_format_to_back_inserter<std::vector>/string_view len = 6000 946 ns 946 ns 735544
BM_format_to_back_inserter<std::deque>/string_view len = 6000 15028 ns 15029 ns 46612
BM_format_to_back_inserter<std::list>/string_view len = 6000 115153 ns 115153 ns 6057
BM_format_to_iterator/std::array string_view len = 6000 122 ns 122 ns 5753940
BM_format_to_iterator/std::string string_view len = 6000 108 ns 108 ns 6507555
BM_format_to_iterator/std::vector string_view len = 6000 107 ns 107 ns 6510450
BM_format_to_iterator/std::deque string_view len = 6000 398 ns 398 ns 1762517

Comparison
Benchmark Time CPU Time Old Time New CPU Old CPU New

BM_sprintf/C string len = 6 -0.2599 -0.2599 5 4 5 4
BM_format/C string len = 6 -0.1094 -0.1095 55 49 55 49
BM_format_to_back_inserterstd::string/C string len = 6 +0.0316 +0.0316 55 57 55 57
BM_format_to_back_inserter<std::vector>/C string len = 6 +0.0204 +0.0204 71 73 71 73
BM_format_to_back_inserter<std::deque>/C string len = 6 +0.0023 +0.0023 154 155 154 155
BM_format_to_back_inserter<std::list>/C string len = 6 +0.0521 +0.0520 130 137 130 137
BM_format_to_iterator/std::array C string len = 6 +0.0317 +0.0317 45 46 45 46
BM_format_to_iterator/std::string C string len = 6 +0.0265 +0.0265 46 47 46 47
BM_format_to_iterator/std::vector C string len = 6 +0.0345 +0.0345 44 46 44 46
BM_format_to_iterator/std::deque C string len = 6 +0.0511 +0.0511 50 53 50 53
BM_format/string len = 6 -0.0981 -0.0981 55 49 55 49
BM_format_to_back_inserterstd::string/string len = 6 -0.0028 -0.0028 56 55 56 55
BM_format_to_back_inserter<std::vector>/string len = 6 +0.0331 +0.0331 70 73 70 73
BM_format_to_back_inserter<std::deque>/string len = 6 -0.0040 -0.0040 155 154 155 154
BM_format_to_back_inserter<std::list>/string len = 6 -0.0019 -0.0019 135 134 135 134
BM_format_to_iterator/std::array string len = 6 +0.0427 +0.0427 45 46 45 46
BM_format_to_iterator/std::string string len = 6 +0.0515 +0.0515 45 47 45 47
BM_format_to_iterator/std::vector string len = 6 +0.0316 +0.0316 45 46 45 46
BM_format_to_iterator/std::deque string len = 6 +0.0475 +0.0475 51 53 51 53
BM_format/string_view len = 6 -0.1267 -0.1267 55 48 55 48
BM_format_to_back_inserterstd::string/string_view len = 6 +0.0283 +0.0283 55 56 55 56
BM_format_to_back_inserter<std::vector>/string_view len = 6 +0.0291 +0.0291 70 72 70 72
BM_format_to_back_inserter<std::deque>/string_view len = 6 -0.0305 -0.0306 157 152 157 152
BM_format_to_back_inserter<std::list>/string_view len = 6 -0.0012 -0.0012 134 134 134 134
BM_format_to_iterator/std::array string_view len = 6 +0.0426 +0.0426 44 46 44 46
BM_format_to_iterator/std::string string_view len = 6 +0.0322 +0.0322 45 46 45 46
BM_format_to_iterator/std::vector string_view len = 6 +0.0309 +0.0309 45 46 45 46
BM_format_to_iterator/std::deque string_view len = 6 +0.0248 +0.0248 51 52 51 52
BM_sprintf/C string len = 60 +0.1633 +0.1633 4 5 4 5
BM_format/C string len = 60 -0.0203 -0.0203 74 72 74 72
BM_format_to_back_inserterstd::string/C string len = 60 +0.1548 +0.1548 74 85 74 85
BM_format_to_back_inserter<std::vector>/C string len = 60 +0.1395 +0.1395 83 95 83 95
BM_format_to_back_inserter<std::deque>/C string len = 60 +0.0157 +0.0157 281 286 281 286
BM_format_to_back_inserter<std::list>/C string len = 60 +0.0191 +0.0191 1157 1179 1157 1179
BM_format_to_iterator/std::array C string len = 60 +0.0283 +0.0283 45 46 45 46
BM_format_to_iterator/std::string C string len = 60 +0.0251 +0.0252 46 47 46 47
BM_format_to_iterator/std::vector C string len = 60 +0.0263 +0.0263 45 46 45 46
BM_format_to_iterator/std::deque C string len = 60 +0.1592 +0.1591 51 59 51 59
BM_format/string len = 60 -0.1466 -0.1466 72 62 72 62
BM_format_to_back_inserterstd::string/string len = 60 +0.0299 +0.0299 72 74 72 74
BM_format_to_back_inserter<std::vector>/string len = 60 +0.0522 +0.0522 82 87 82 87
BM_format_to_back_inserter<std::deque>/string len = 60 -0.0099 -0.0099 280 278 280 278
BM_format_to_back_inserter<std::list>/string len = 60 +0.0062 +0.0062 1162 1169 1162 1170
BM_format_to_iterator/std::array string len = 60 +0.0430 +0.0430 45 46 45 46
BM_format_to_iterator/std::string string len = 60 -0.0466 -0.0466 50 47 50 47
BM_format_to_iterator/std::vector string len = 60 -0.0693 -0.0693 50 46 50 46
BM_format_to_iterator/std::deque string len = 60 +0.0275 +0.0275 51 52 51 52
BM_format/string_view len = 60 -0.1034 -0.1034 73 65 73 65
BM_format_to_back_inserterstd::string/string_view len = 60 +0.0790 +0.0790 73 78 73 78
BM_format_to_back_inserter<std::vector>/string_view len = 60 +0.0735 +0.0735 82 88 82 88
BM_format_to_back_inserter<std::deque>/string_view len = 60 -0.0103 -0.0104 283 280 283 280
BM_format_to_back_inserter<std::list>/string_view len = 60 +0.0101 +0.0101 1162 1174 1162 1174
BM_format_to_iterator/std::array string_view len = 60 +0.0484 +0.0484 44 46 44 46
BM_format_to_iterator/std::string string_view len = 60 +0.0387 +0.0387 45 47 45 47
BM_format_to_iterator/std::vector string_view len = 60 +0.0402 +0.0402 45 47 45 47
BM_format_to_iterator/std::deque string_view len = 60 +0.0508 +0.0508 50 53 50 53
BM_sprintf/C string len = 6000 -0.3337 -0.3337 116 77 116 77
BM_format/C string len = 6000 -0.6500 -0.6500 1000 350 1000 350
BM_format_to_back_inserterstd::string/C string len = 6000 -0.0104 -0.0105 1002 992 1002 992
BM_format_to_back_inserter<std::vector>/C string len = 6000 +0.0630 +0.0630 956 1016 956 1016
BM_format_to_back_inserter<std::deque>/C string len = 6000 +0.0175 +0.0175 14898 15158 14898 15159
BM_format_to_back_inserter<std::list>/C string len = 6000 +0.0073 +0.0074 114860 115703 114859 115705
BM_format_to_iterator/std::array C string len = 6000 +0.0504 +0.0504 158 166 158 166
BM_format_to_iterator/std::string C string len = 6000 -0.0486 -0.0486 161 153 161 153
BM_format_to_iterator/std::vector C string len = 6000 -0.0483 -0.0483 157 150 157 150
BM_format_to_iterator/std::deque C string len = 6000 +0.0459 +0.0459 445 465 445 465
BM_format/string len = 6000 -0.6975 -0.6975 929 281 929 281
BM_format_to_back_inserterstd::string/string len = 6000 +0.0050 +0.0050 930 935 930 935
BM_format_to_back_inserter<std::vector>/string len = 6000 +0.0321 +0.0322 910 939 910 939
BM_format_to_back_inserter<std::deque>/string len = 6000 +0.0130 +0.0130 14875 15069 14876 15069
BM_format_to_back_inserter<std::list>/string len = 6000 +0.0052 +0.0052 114937 115537 114936 115539
BM_format_to_iterator/std::array string len = 6000 +0.0211 +0.0211 118 120 118 120
BM_format_to_iterator/std::string string len = 6000 +0.0146 +0.0146 106 108 106 108
BM_format_to_iterator/std::vector string len = 6000 +0.0048 +0.0048 106 107 106 107
BM_format_to_iterator/std::deque string len = 6000 +0.0150 +0.0150 391 397 391 397
BM_format/string_view len = 6000 -0.6989 -0.6989 935 282 935 282
BM_format_to_back_inserterstd::string/string_view len = 6000 -0.0083 -0.0083 934 927 934 927
BM_format_to_back_inserter<std::vector>/string_view len = 6000 +0.0566 +0.0566 895 946 895 946
BM_format_to_back_inserter<std::deque>/string_view len = 6000 +0.0111 +0.0110 14864 15028 14865 15029
BM_format_to_back_inserter<std::list>/string_view len = 6000 +0.0010 +0.0009 115042 115153 115044 115153
BM_format_to_iterator/std::array string_view len = 6000 +0.0560 +0.0560 115 122 115 122
BM_format_to_iterator/std::string string_view len = 6000 -0.0693 -0.0693 116 108 116 108
BM_format_to_iterator/std::vector string_view len = 6000 -0.0703 -0.0703 115 107 115 107
BM_format_to_iterator/std::deque string_view len = 6000 +0.0271 +0.0271 387 398 387 398
OVERALL_GEOMEAN -0.0350 -0.0350 0 0 0 0

format:
Before

Benchmark Time CPU Iterations UserCounters...

BM_format_string/1 55.5 ns 55.5 ns 12463288 bytes_per_second=17.187Mi/s
BM_format_string/2 27.6 ns 27.6 ns 25421994 bytes_per_second=69.1874Mi/s
BM_format_string/4 14.0 ns 14.0 ns 49785656 bytes_per_second=271.524Mi/s
BM_format_string/8 7.07 ns 7.07 ns 99247048 bytes_per_second=1.05444Gi/s
BM_format_string/16 3.53 ns 3.53 ns 198072224 bytes_per_second=4.21726Gi/s
BM_format_string/32 2.31 ns 2.31 ns 302771136 bytes_per_second=12.9138Gi/s
BM_format_string/64 1.15 ns 1.15 ns 606646976 bytes_per_second=51.7527Gi/s
BM_format_string/128 0.597 ns 0.597 ns 1172263936 bytes_per_second=199.688Gi/s
BM_format_string/256 0.327 ns 0.327 ns 2148927744 bytes_per_second=728.678Gi/s
BM_format_string/512 0.248 ns 0.248 ns 2821635584 bytes_per_second=1.8779Ti/s
BM_format_string/1024 0.203 ns 0.203 ns 3433579520 bytes_per_second=4.57798Ti/s
BM_format_string/2048 0.164 ns 0.164 ns 4277524480 bytes_per_second=11.3793Ti/s
BM_format_string/4096 0.137 ns 0.137 ns 5122269184 bytes_per_second=27.2589Ti/s
BM_format_string/8192 0.126 ns 0.126 ns 5564243968 bytes_per_second=59.2812Ti/s
BM_format_string/16384 0.136 ns 0.136 ns 5153013760 bytes_per_second=109.492Ti/s
BM_format_string/32768 0.135 ns 0.135 ns 5165088768 bytes_per_second=219.985Ti/s
BM_format_string/65536 0.243 ns 0.242 ns 2930180096 bytes_per_second=246.57Ti/s
BM_format_string/131072 0.490 ns 0.489 ns 1437990912 bytes_per_second=243.75Ti/s
BM_format_string/262144 0.593 ns 0.592 ns 1183055872 bytes_per_second=402.931Ti/s
BM_format_string/524288 0.643 ns 0.641 ns 1092616192 bytes_per_second=743.445Ti/s
BM_format_string/1048576 0.669 ns 0.668 ns 1045430272 bytes_per_second=1.39478Pi/s
BM_format_string<wchar_t>/1 56.0 ns 55.9 ns 12511543 bytes_per_second=68.2628Mi/s
BM_format_string<wchar_t>/2 28.0 ns 27.9 ns 25062366 bytes_per_second=273.519Mi/s
BM_format_string<wchar_t>/4 14.0 ns 14.0 ns 50257068 bytes_per_second=1.06742Gi/s
BM_format_string<wchar_t>/8 9.24 ns 9.21 ns 76118616 bytes_per_second=3.23473Gi/s
BM_format_string<wchar_t>/16 4.66 ns 4.65 ns 151420352 bytes_per_second=12.8261Gi/s
BM_format_string<wchar_t>/32 2.35 ns 2.35 ns 298417600 bytes_per_second=50.7972Gi/s
BM_format_string<wchar_t>/64 1.35 ns 1.34 ns 521608704 bytes_per_second=177.502Gi/s
BM_format_string<wchar_t>/128 1.03 ns 1.03 ns 680946304 bytes_per_second=463.91Gi/s
BM_format_string<wchar_t>/256 0.849 ns 0.847 ns 825871104 bytes_per_second=1.09901Ti/s
BM_format_string<wchar_t>/512 0.681 ns 0.679 ns 1033245696 bytes_per_second=2.74383Ti/s
BM_format_string<wchar_t>/1024 0.576 ns 0.575 ns 1219777536 bytes_per_second=6.48343Ti/s
BM_format_string<wchar_t>/2048 0.515 ns 0.514 ns 1361629184 bytes_per_second=14.4881Ti/s
BM_format_string<wchar_t>/4096 0.546 ns 0.545 ns 1285427200 bytes_per_second=27.3342Ti/s
BM_format_string<wchar_t>/8192 0.550 ns 0.548 ns 1277042688 bytes_per_second=54.3343Ti/s
BM_format_string<wchar_t>/16384 0.583 ns 0.581 ns 1203879936 bytes_per_second=102.544Ti/s
BM_format_string<wchar_t>/32768 0.640 ns 0.638 ns 1095139328 bytes_per_second=186.82Ti/s
BM_format_string<wchar_t>/65536 0.642 ns 0.640 ns 1093337088 bytes_per_second=372.283Ti/s
BM_format_string<wchar_t>/131072 0.655 ns 0.654 ns 1070596096 bytes_per_second=729.428Ti/s
BM_format_string<wchar_t>/262144 2.68 ns 2.67 ns 262406144 bytes_per_second=357.446Ti/s
BM_format_string<wchar_t>/524288 2.13 ns 2.13 ns 330301440 bytes_per_second=897.574Ti/s
BM_format_string<wchar_t>/1048576 2.44 ns 2.43 ns 288358400 bytes_per_second=1.53149Pi/s

After

Benchmark Time CPU Iterations UserCounters...

BM_format_string/1 49.3 ns 49.1 ns 14230742 bytes_per_second=19.4054Mi/s
BM_format_string/2 24.8 ns 24.8 ns 28253114 bytes_per_second=77.0465Mi/s
BM_format_string/4 12.4 ns 12.4 ns 56381440 bytes_per_second=307.462Mi/s
BM_format_string/8 6.23 ns 6.21 ns 112951232 bytes_per_second=1.19924Gi/s
BM_format_string/16 3.10 ns 3.09 ns 225822496 bytes_per_second=4.81566Gi/s
BM_format_string/32 1.98 ns 1.98 ns 354208192 bytes_per_second=15.0825Gi/s
BM_format_string/64 0.990 ns 0.987 ns 714296384 bytes_per_second=60.3689Gi/s
BM_format_string/128 0.504 ns 0.503 ns 1399988480 bytes_per_second=237.144Gi/s
BM_format_string/256 0.335 ns 0.334 ns 2084828928 bytes_per_second=712.859Gi/s
BM_format_string/512 0.187 ns 0.186 ns 3760082432 bytes_per_second=2.50102Ti/s
BM_format_string/1024 0.109 ns 0.108 ns 6455339008 bytes_per_second=8.59552Ti/s
BM_format_string/2048 0.080 ns 0.080 ns 8754006016 bytes_per_second=23.2731Ti/s
BM_format_string/4096 0.051 ns 0.051 ns 13786701824 bytes_per_second=73.4088Ti/s
BM_format_string/8192 0.042 ns 0.042 ns 16851435520 bytes_per_second=178.737Ti/s
BM_format_string/16384 0.122 ns 0.122 ns 5746589696 bytes_per_second=122.029Ti/s
BM_format_string/32768 0.107 ns 0.106 ns 6571687936 bytes_per_second=280.122Ti/s
BM_format_string/65536 0.102 ns 0.102 ns 6876626944 bytes_per_second=584.381Ti/s
BM_format_string/131072 0.106 ns 0.105 ns 6643122176 bytes_per_second=1.10413Pi/s
BM_format_string/262144 0.589 ns 0.587 ns 1189609472 bytes_per_second=406.438Ti/s
BM_format_string/524288 0.644 ns 0.642 ns 1088946176 bytes_per_second=743.064Ti/s
BM_format_string/1048576 0.672 ns 0.670 ns 1039138816 bytes_per_second=1.38968Pi/s
BM_format_string<wchar_t>/1 48.7 ns 48.6 ns 14423178 bytes_per_second=78.5263Mi/s
BM_format_string<wchar_t>/2 24.4 ns 24.3 ns 28831748 bytes_per_second=313.869Mi/s
BM_format_string<wchar_t>/4 12.2 ns 12.2 ns 57661220 bytes_per_second=1.2253Gi/s
BM_format_string<wchar_t>/8 7.81 ns 7.79 ns 89887592 bytes_per_second=3.82675Gi/s
BM_format_string<wchar_t>/16 3.88 ns 3.87 ns 180450176 bytes_per_second=15.418Gi/s
BM_format_string<wchar_t>/32 1.98 ns 1.98 ns 354046112 bytes_per_second=60.3262Gi/s
BM_format_string<wchar_t>/64 1.02 ns 1.01 ns 689511680 bytes_per_second=234.906Gi/s
BM_format_string<wchar_t>/128 0.577 ns 0.576 ns 1215361408 bytes_per_second=828.297Gi/s
BM_format_string<wchar_t>/256 0.804 ns 0.802 ns 872249088 bytes_per_second=1.16111Ti/s
BM_format_string<wchar_t>/512 0.642 ns 0.641 ns 1093858304 bytes_per_second=2.90766Ti/s
BM_format_string<wchar_t>/1024 0.517 ns 0.516 ns 1354798080 bytes_per_second=7.21845Ti/s
BM_format_string<wchar_t>/2048 0.469 ns 0.467 ns 1491910656 bytes_per_second=15.9386Ti/s
BM_format_string<wchar_t>/4096 0.794 ns 0.792 ns 883822592 bytes_per_second=18.8156Ti/s
BM_format_string<wchar_t>/8192 0.722 ns 0.720 ns 971718656 bytes_per_second=41.3996Ti/s
BM_format_string<wchar_t>/16384 0.703 ns 0.701 ns 998031360 bytes_per_second=85.0369Ti/s
BM_format_string<wchar_t>/32768 0.724 ns 0.720 ns 971538432 bytes_per_second=165.467Ti/s
BM_format_string<wchar_t>/65536 0.745 ns 0.744 ns 941228032 bytes_per_second=320.665Ti/s
BM_format_string<wchar_t>/131072 0.742 ns 0.740 ns 945422336 bytes_per_second=644.032Ti/s
BM_format_string<wchar_t>/262144 2.99 ns 2.98 ns 234881024 bytes_per_second=319.75Ti/s
BM_format_string<wchar_t>/524288 3.31 ns 3.30 ns 212860928 bytes_per_second=578.085Ti/s
BM_format_string<wchar_t>/1048576 2.69 ns 2.68 ns 260046848 bytes_per_second=1.39081Pi/s

Comparison
Benchmark Time CPU Time Old Time New CPU Old CPU New

BM_format_string/1 -0.1122 -0.1143 55 49 55 49
BM_format_string/2 -0.0999 -0.1020 28 25 28 25
BM_format_string/4 -0.1148 -0.1169 14 12 14 12
BM_format_string/8 -0.1186 -0.1207 7 6 7 6
BM_format_string/16 -0.1222 -0.1243 4 3 4 3
BM_format_string/32 -0.1417 -0.1438 2 2 2 2
BM_format_string/64 -0.1407 -0.1427 1 1 1 1
BM_format_string/128 -0.1559 -0.1579 1 1 1 1
BM_format_string/256 +0.0249 +0.0222 0 0 0 0
BM_format_string/512 -0.2473 -0.2491 0 0 0 0
BM_format_string/1024 -0.4661 -0.4674 0 0 0 0
BM_format_string/2048 -0.5096 -0.5111 0 0 0 0
BM_format_string/4096 -0.6278 -0.6287 0 0 0 0
BM_format_string/8192 -0.6674 -0.6683 0 0 0 0
BM_format_string/16384 -0.1005 -0.1027 0 0 0 0
BM_format_string/32768 -0.2127 -0.2147 0 0 0 0
BM_format_string/65536 -0.5796 -0.5781 0 0 0 0
BM_format_string/131072 -0.7844 -0.7844 0 0 0 0
BM_format_string/262144 -0.0073 -0.0086 1 1 1 1
BM_format_string/524288 +0.0017 +0.0005 1 1 1 1
BM_format_string/1048576 +0.0039 +0.0037 1 1 1 1
BM_format_string<wchar_t>/1 -0.1304 -0.1307 56 49 56 49
BM_format_string<wchar_t>/2 -0.1285 -0.1286 28 24 28 24
BM_format_string<wchar_t>/4 -0.1288 -0.1288 14 12 14 12
BM_format_string<wchar_t>/8 -0.1547 -0.1547 9 8 9 8
BM_format_string<wchar_t>/16 -0.1681 -0.1681 5 4 5 4
BM_format_string<wchar_t>/32 -0.1579 -0.1580 2 2 2 2
BM_format_string<wchar_t>/64 -0.2443 -0.2444 1 1 1 1
BM_format_string<wchar_t>/128 -0.4400 -0.4399 1 1 1 1
BM_format_string<wchar_t>/256 -0.0535 -0.0535 1 1 1 1
BM_format_string<wchar_t>/512 -0.0563 -0.0563 1 1 1 1
BM_format_string<wchar_t>/1024 -0.1018 -0.1018 1 1 1 1
BM_format_string<wchar_t>/2048 -0.0910 -0.0910 1 0 1 0
BM_format_string<wchar_t>/4096 +0.4528 +0.4527 1 1 1 1
BM_format_string<wchar_t>/8192 +0.3121 +0.3124 1 1 1 1
BM_format_string<wchar_t>/16384 +0.2059 +0.2059 1 1 1 1
BM_format_string<wchar_t>/32768 +0.1316 +0.1290 1 1 1 1
BM_format_string<wchar_t>/65536 +0.1604 +0.1610 1 1 1 1
BM_format_string<wchar_t>/131072 +0.1326 +0.1326 1 1 1 1
BM_format_string<wchar_t>/262144 +0.1181 +0.1179 3 3 3 3
BM_format_string<wchar_t>/524288 +0.5515 +0.5527 2 3 2 3
BM_format_string<wchar_t>/1048576 +0.1007 +0.1011 2 3 2 3
OVERALL_GEOMEAN -0.1685 -0.1693 0 0 0 0

This patch is the start of a series to improve the speed of std::format,
std::format_to, std::format_to_n, and std::formatted_size.

This is mostly achieved by changing the __output_buffer class. This new
__output_buffer class also makes it easier to implement buffering for
P3107R5 "Permit an efficient implementation of std::print"
The formatter specializations for _CharT* and const _CharT* typically
write all elements in a loop. This format's internal functions are
optimized for larger writes.

Instead of writing one element at a time conversion the range to a
basic_string_view and write that instead.

For C string of 6 characters this is a bit slower, but for 60 characters
it's faster. The improvements for back_inserter<std::list<_CharT>> are not
as great as the others; it just gets as slow as basic_string_view<_CharT>.

Before
---------------------------------------------------------------------------------------------------------------
Benchmark                                                                     Time             CPU   Iterations
---------------------------------------------------------------------------------------------------------------
BM_sprintf/C string len = 6                                                4.81 ns         4.80 ns    145890280
BM_format/C string len = 6                                                 52.6 ns         52.4 ns     13252327
BM_format_to_back_inserter<std::string>/C string len = 6                   53.0 ns         52.8 ns     13262680
BM_format_to_back_inserter<std::vector<char>>/C string len = 6             69.7 ns         69.6 ns     10045636
BM_format_to_back_inserter<std::deque<char>>/C string len = 6               148 ns          148 ns      4729368
BM_format_to_back_inserter<std::list<char>>/C string len = 6                127 ns          126 ns      5538441
BM_format_to_iterator/<std::array> C string len = 6                        42.9 ns         42.8 ns     16367158
BM_format_to_iterator/<std::string> C string len = 6                       43.5 ns         43.4 ns     16141644
BM_format_to_iterator/<std::vector> C string len = 6                       42.9 ns         42.8 ns     16366718
BM_format_to_iterator/<std::deque> C string len = 6                        47.8 ns         47.7 ns     14686488
BM_format/string len = 6                                                   55.3 ns         55.2 ns     12696889
BM_format_to_back_inserter<std::string>/string len = 6                     55.4 ns         55.2 ns     12660731
BM_format_to_back_inserter<std::vector<char>>/string len = 6               70.7 ns         70.5 ns      9927313
BM_format_to_back_inserter<std::deque<char>>/string len = 6                 153 ns          153 ns      4573936
BM_format_to_back_inserter<std::list<char>>/string len = 6                  128 ns          128 ns      5486033
BM_format_to_iterator/<std::array> string len = 6                          44.6 ns         44.5 ns     15758122
BM_format_to_iterator/<std::string> string len = 6                         44.7 ns         44.6 ns     15690226
BM_format_to_iterator/<std::vector> string len = 6                         44.3 ns         44.2 ns     15715898
BM_format_to_iterator/<std::deque> string len = 6                          50.3 ns         50.1 ns     13958635
BM_format/string_view len = 6                                              54.2 ns         54.1 ns     12929525
BM_format_to_back_inserter<std::string>/string_view len = 6                54.3 ns         54.1 ns     12929219
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6          70.0 ns         69.8 ns     10022355
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6            153 ns          152 ns      4585749
BM_format_to_back_inserter<std::list<char>>/string_view len = 6             128 ns          128 ns      5489760
BM_format_to_iterator/<std::array> string_view len = 6                     44.2 ns         44.1 ns     15884839
BM_format_to_iterator/<std::string> string_view len = 6                    44.8 ns         44.6 ns     15664278
BM_format_to_iterator/<std::vector> string_view len = 6                    44.7 ns         44.6 ns     15716983
BM_format_to_iterator/<std::deque> string_view len = 6                     50.3 ns         50.2 ns     13936091
BM_sprintf/C string len = 60                                               4.16 ns         4.15 ns    168764227
BM_format/C string len = 60                                                 169 ns          169 ns      4144060
BM_format_to_back_inserter<std::string>/C string len = 60                   167 ns          167 ns      4203915
BM_format_to_back_inserter<std::vector<char>>/C string len = 60             177 ns          176 ns      3965619
BM_format_to_back_inserter<std::deque<char>>/C string len = 60              383 ns          382 ns      1832531
BM_format_to_back_inserter<std::list<char>>/C string len = 60              1270 ns         1267 ns       552686
BM_format_to_iterator/<std::array> C string len = 60                        141 ns          140 ns      4988441
BM_format_to_iterator/<std::string> C string len = 60                       141 ns          141 ns      4956101
BM_format_to_iterator/<std::vector> C string len = 60                       141 ns          141 ns      4963443
BM_format_to_iterator/<std::deque> C string len = 60                        144 ns          143 ns      4893139
BM_format/string len = 60                                                  73.4 ns         73.2 ns      9548455
BM_format_to_back_inserter<std::string>/string len = 60                    73.2 ns         73.0 ns      9524524
BM_format_to_back_inserter<std::vector<char>>/string len = 60              81.6 ns         81.4 ns      8584033
BM_format_to_back_inserter<std::deque<char>>/string len = 60                279 ns          279 ns      2515146
BM_format_to_back_inserter<std::list<char>>/string len = 60                1177 ns         1174 ns       597172
BM_format_to_iterator/<std::array> string len = 60                         44.5 ns         44.4 ns     15753131
BM_format_to_iterator/<std::string> string len = 60                        44.7 ns         44.6 ns     15692630
BM_format_to_iterator/<std::vector> string len = 60                        44.8 ns         44.7 ns     15664689
BM_format_to_iterator/<std::deque> string len = 60                         50.6 ns         50.5 ns     13838617
BM_format/string_view len = 60                                             72.8 ns         72.6 ns      9674007
BM_format_to_back_inserter<std::string>/string_view len = 60               72.7 ns         72.6 ns      9638209
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60         82.6 ns         82.4 ns      8496602
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60           280 ns          280 ns      2508982
BM_format_to_back_inserter<std::list<char>>/string_view len = 60           1176 ns         1173 ns       597714
BM_format_to_iterator/<std::array> string_view len = 60                    44.2 ns         44.1 ns     15896934
BM_format_to_iterator/<std::string> string_view len = 60                   44.7 ns         44.6 ns     15695427
BM_format_to_iterator/<std::vector> string_view len = 60                   44.7 ns         44.6 ns     15680899
BM_format_to_iterator/<std::deque> string_view len = 60                    50.3 ns         50.1 ns     13962755
BM_sprintf/C string len = 6000                                              114 ns          114 ns      6170153
BM_format/C string len = 6000                                             11792 ns        11763 ns        59619
BM_format_to_back_inserter<std::string>/C string len = 6000               11778 ns        11746 ns        59572
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000         11715 ns        11686 ns        60053
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000          25464 ns        25403 ns        27538
BM_format_to_back_inserter<std::list<char>>/C string len = 6000          126044 ns       125726 ns         5572
BM_format_to_iterator/<std::array> C string len = 6000                    10792 ns        10766 ns        64943
BM_format_to_iterator/<std::string> C string len = 6000                   10791 ns        10761 ns        64918
BM_format_to_iterator/<std::vector> C string len = 6000                   10775 ns        10750 ns        65149
BM_format_to_iterator/<std::deque> C string len = 6000                    11242 ns        11215 ns        62542
BM_format/string len = 6000                                                 919 ns          917 ns       763961
BM_format_to_back_inserter<std::string>/string len = 6000                   920 ns          917 ns       763094
BM_format_to_back_inserter<std::vector<char>>/string len = 6000             888 ns          886 ns       793468
BM_format_to_back_inserter<std::deque<char>>/string len = 6000            14999 ns        14963 ns        46758
BM_format_to_back_inserter<std::list<char>>/string len = 6000            114504 ns       114213 ns         6130
BM_format_to_iterator/<std::array> string len = 6000                        120 ns          120 ns      5823426
BM_format_to_iterator/<std::string> string len = 6000                       106 ns          106 ns      6609299
BM_format_to_iterator/<std::vector> string len = 6000                       106 ns          106 ns      6613867
BM_format_to_iterator/<std::deque> string len = 6000                        367 ns          366 ns      1912818
BM_format/string_view len = 6000                                            910 ns          907 ns       771491
BM_format_to_back_inserter<std::string>/string_view len = 6000              911 ns          909 ns       770065
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000        878 ns          876 ns       794976
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000       15031 ns        14994 ns        46651
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000       114510 ns       114219 ns         6130
BM_format_to_iterator/<std::array> string_view len = 6000                   121 ns          120 ns      5814249
BM_format_to_iterator/<std::string> string_view len = 6000                  116 ns          115 ns      6072315
BM_format_to_iterator/<std::vector> string_view len = 6000                  115 ns          115 ns      6095762
BM_format_to_iterator/<std::deque> string_view len = 6000                   351 ns          350 ns      2002175

After
---------------------------------------------------------------------------------------------------------------
Benchmark                                                                     Time             CPU   Iterations
---------------------------------------------------------------------------------------------------------------
BM_sprintf/C string len = 6                                                4.83 ns         4.83 ns    145502957
BM_format/C string len = 6                                                 55.1 ns         55.1 ns     12687656
BM_format_to_back_inserter<std::string>/C string len = 6                   55.1 ns         55.1 ns     12691642
BM_format_to_back_inserter<std::vector<char>>/C string len = 6             71.2 ns         71.3 ns      9819560
BM_format_to_back_inserter<std::deque<char>>/C string len = 6               154 ns          154 ns      4548709
BM_format_to_back_inserter<std::list<char>>/C string len = 6                131 ns          131 ns      5338318
BM_format_to_iterator/<std::array> C string len = 6                        45.0 ns         45.0 ns     15569429
BM_format_to_iterator/<std::string> C string len = 6                       45.9 ns         45.9 ns     15240594
BM_format_to_iterator/<std::vector> C string len = 6                       44.4 ns         44.4 ns     15768343
BM_format_to_iterator/<std::deque> C string len = 6                        50.1 ns         50.1 ns     13995837
BM_format/string len = 6                                                   54.8 ns         54.8 ns     12738209
BM_format_to_back_inserter<std::string>/string len = 6                     55.4 ns         55.4 ns     12634483
BM_format_to_back_inserter<std::vector<char>>/string len = 6               70.4 ns         70.4 ns      9948288
BM_format_to_back_inserter<std::deque<char>>/string len = 6                 154 ns          154 ns      4531741
BM_format_to_back_inserter<std::list<char>>/string len = 6                  132 ns          132 ns      5289798
BM_format_to_iterator/<std::array> string len = 6                          44.5 ns         44.5 ns     15743437
BM_format_to_iterator/<std::string> string len = 6                         44.9 ns         44.9 ns     15591961
BM_format_to_iterator/<std::vector> string len = 6                         45.0 ns         45.0 ns     15541308
BM_format_to_iterator/<std::deque> string len = 6                          50.5 ns         50.5 ns     13837884
BM_format/string_view len = 6                                              54.5 ns         54.5 ns     12833591
BM_format_to_back_inserter<std::string>/string_view len = 6                54.6 ns         54.6 ns     12818233
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6          69.9 ns         69.9 ns     10018025
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6            154 ns          154 ns      4534215
BM_format_to_back_inserter<std::list<char>>/string_view len = 6             131 ns          131 ns      5337938
BM_format_to_iterator/<std::array> string_view len = 6                     44.2 ns         44.2 ns     15854695
BM_format_to_iterator/<std::string> string_view len = 6                    45.0 ns         45.0 ns     15551054
BM_format_to_iterator/<std::vector> string_view len = 6                    45.0 ns         45.0 ns     15567905
BM_format_to_iterator/<std::deque> string_view len = 6                     50.5 ns         50.5 ns     13858261
BM_sprintf/C string len = 60                                               4.16 ns         4.16 ns    168066307
BM_format/C string len = 60                                                73.8 ns         73.8 ns      9487364
BM_format_to_back_inserter<std::string>/C string len = 60                  73.7 ns         73.7 ns      9492371
BM_format_to_back_inserter<std::vector<char>>/C string len = 60            83.1 ns         83.1 ns      8399017
BM_format_to_back_inserter<std::deque<char>>/C string len = 60              284 ns          284 ns      2466510
BM_format_to_back_inserter<std::list<char>>/C string len = 60              1177 ns         1177 ns       592514
BM_format_to_iterator/<std::array> C string len = 60                       44.9 ns         44.9 ns     15558172
BM_format_to_iterator/<std::string> C string len = 60                      45.8 ns         45.8 ns     15283103
BM_format_to_iterator/<std::vector> C string len = 60                      44.6 ns         44.6 ns     15678967
BM_format_to_iterator/<std::deque> C string len = 60                       50.5 ns         50.5 ns     13839524
BM_format/string len = 60                                                  72.2 ns         72.2 ns      9687634
BM_format_to_back_inserter<std::string>/string len = 60                    72.0 ns         72.1 ns      9695746
BM_format_to_back_inserter<std::vector<char>>/string len = 60              82.3 ns         82.3 ns      8509528
BM_format_to_back_inserter<std::deque<char>>/string len = 60                279 ns          279 ns      2506108
BM_format_to_back_inserter<std::list<char>>/string len = 60                1180 ns         1180 ns       592963
BM_format_to_iterator/<std::array> string len = 60                         44.7 ns         44.7 ns     15657865
BM_format_to_iterator/<std::string> string len = 60                        45.0 ns         45.0 ns     15569049
BM_format_to_iterator/<std::vector> string len = 60                        44.9 ns         44.9 ns     15576187
BM_format_to_iterator/<std::deque> string len = 60                         50.7 ns         50.7 ns     13803188
BM_format/string_view len = 60                                             72.4 ns         72.4 ns      9663061
BM_format_to_back_inserter<std::string>/string_view len = 60               72.8 ns         72.8 ns      9638941
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60         81.9 ns         81.9 ns      8529931
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60           283 ns          283 ns      2471522
BM_format_to_back_inserter<std::list<char>>/string_view len = 60           1177 ns         1177 ns       594752
BM_format_to_iterator/<std::array> string_view len = 60                    44.2 ns         44.2 ns     15841413
BM_format_to_iterator/<std::string> string_view len = 60                   45.1 ns         45.1 ns     15546279
BM_format_to_iterator/<std::vector> string_view len = 60                   45.0 ns         45.0 ns     15555756
BM_format_to_iterator/<std::deque> string_view len = 60                    50.1 ns         50.1 ns     10000000
BM_sprintf/C string len = 6000                                              344 ns          344 ns      2037753
BM_format/C string len = 6000                                               980 ns          980 ns       713341
BM_format_to_back_inserter<std::string>/C string len = 6000                 979 ns          979 ns       709571
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000           944 ns          944 ns       744518
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000          14916 ns        14915 ns        46875
BM_format_to_back_inserter<std::list<char>>/C string len = 6000          114686 ns       114688 ns         6110
BM_format_to_iterator/<std::array> C string len = 6000                      159 ns          159 ns      4394506
BM_format_to_iterator/<std::string> C string len = 6000                     159 ns          159 ns      4384577
BM_format_to_iterator/<std::vector> C string len = 6000                     159 ns          159 ns      4393225
BM_format_to_iterator/<std::deque> C string len = 6000                      437 ns          437 ns      1601253
BM_format/string len = 6000                                                 929 ns          929 ns       751889
BM_format_to_back_inserter<std::string>/string len = 6000                   933 ns          933 ns       752042
BM_format_to_back_inserter<std::vector<char>>/string len = 6000             892 ns          892 ns       785064
BM_format_to_back_inserter<std::deque<char>>/string len = 6000            14840 ns        14839 ns        47177
BM_format_to_back_inserter<std::list<char>>/string len = 6000            114940 ns       114942 ns         6095
BM_format_to_iterator/<std::array> string len = 6000                        144 ns          144 ns      4859849
BM_format_to_iterator/<std::string> string len = 6000                       106 ns          106 ns      6565564
BM_format_to_iterator/<std::vector> string len = 6000                       107 ns          107 ns      6584152
BM_format_to_iterator/<std::deque> string len = 6000                        368 ns          368 ns      1904727
BM_format/string_view len = 6000                                            919 ns          919 ns       760401
BM_format_to_back_inserter<std::string>/string_view len = 6000              917 ns          917 ns       760934
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000        880 ns          880 ns       796244
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000       14854 ns        14853 ns        47101
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000       114963 ns       114967 ns         6086
BM_format_to_iterator/<std::array> string_view len = 6000                   117 ns          117 ns      5974080
BM_format_to_iterator/<std::string> string_view len = 6000                  116 ns          116 ns      6016080
BM_format_to_iterator/<std::vector> string_view len = 6000                  116 ns          116 ns      6053780
BM_format_to_iterator/<std::deque> string_view len = 6000                   351 ns          351 ns      1993879

Comparing libcxx/benchmarks/1/write_string_comparison.bench.out to libcxx/benchmarks/2/write_string_comparison.bench.out
Benchmark                                                                              Time             CPU      Time Old      Time New       CPU Old       CPU New
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
BM_sprintf/C string len = 6                                                         +0.0034         +0.0058             5             5             5             5
BM_format/C string len = 6                                                          +0.0484         +0.0508            53            55            52            55
BM_format_to_back_inserter<std::string>/C string len = 6                            +0.0395         +0.0424            53            55            53            55
BM_format_to_back_inserter<std::vector<char>>/C string len = 6                      +0.0220         +0.0244            70            71            70            71
BM_format_to_back_inserter<std::deque<char>>/C string len = 6                       +0.0399         +0.0424           148           154           148           154
BM_format_to_back_inserter<std::list<char>>/C string len = 6                        +0.0339         +0.0365           127           131           126           131
BM_format_to_iterator/<std::array> C string len = 6                                 +0.0494         +0.0520            43            45            43            45
BM_format_to_iterator/<std::string> C string len = 6                                +0.0539         +0.0568            44            46            43            46
BM_format_to_iterator/<std::vector> C string len = 6                                +0.0359         +0.0384            43            44            43            44
BM_format_to_iterator/<std::deque> C string len = 6                                 +0.0488         +0.0513            48            50            48            50
BM_format/string len = 6                                                            -0.0105         -0.0081            55            55            55            55
BM_format_to_back_inserter<std::string>/string len = 6                              +0.0008         +0.0036            55            55            55            55
BM_format_to_back_inserter<std::vector<char>>/string len = 6                        -0.0046         -0.0021            71            70            71            70
BM_format_to_back_inserter<std::deque<char>>/string len = 6                         +0.0066         +0.0091           153           154           153           154
BM_format_to_back_inserter<std::list<char>>/string len = 6                          +0.0291         +0.0316           128           132           128           132
BM_format_to_iterator/<std::array> string len = 6                                   -0.0030         -0.0006            45            44            44            44
BM_format_to_iterator/<std::string> string len = 6                                  +0.0045         +0.0069            45            45            45            45
BM_format_to_iterator/<std::vector> string len = 6                                  +0.0150         +0.0177            44            45            44            45
BM_format_to_iterator/<std::deque> string len = 6                                   +0.0059         +0.0084            50            51            50            51
BM_format/string_view len = 6                                                       +0.0050         +0.0075            54            55            54            55
BM_format_to_back_inserter<std::string>/string_view len = 6                         +0.0052         +0.0081            54            55            54            55
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6                   -0.0017         +0.0008            70            70            70            70
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6                    +0.0113         +0.0137           153           154           152           154
BM_format_to_back_inserter<std::list<char>>/string_view len = 6                     +0.0260         +0.0286           128           131           128           131
BM_format_to_iterator/<std::array> string_view len = 6                              -0.0006         +0.0021            44            44            44            44
BM_format_to_iterator/<std::string> string_view len = 6                             +0.0059         +0.0084            45            45            45            45
BM_format_to_iterator/<std::vector> string_view len = 6                             +0.0083         +0.0108            45            45            45            45
BM_format_to_iterator/<std::deque> string_view len = 6                              +0.0048         +0.0073            50            51            50            51
BM_sprintf/C string len = 60                                                        +0.0002         +0.0029             4             4             4             4
BM_format/C string len = 60                                                         -0.5640         -0.5629           169            74           169            74
BM_format_to_back_inserter<std::string>/C string len = 60                           -0.5592         -0.5582           167            74           167            74
BM_format_to_back_inserter<std::vector<char>>/C string len = 60                     -0.5294         -0.5282           177            83           176            83
BM_format_to_back_inserter<std::deque<char>>/C string len = 60                      -0.2591         -0.2570           383           284           382           284
BM_format_to_back_inserter<std::list<char>>/C string len = 60                       -0.0730         -0.0707          1270          1177          1267          1177
BM_format_to_iterator/<std::array> C string len = 60                                -0.6804         -0.6797           141            45           140            45
BM_format_to_iterator/<std::string> C string len = 60                               -0.6759         -0.6750           141            46           141            46
BM_format_to_iterator/<std::vector> C string len = 60                               -0.6849         -0.6841           141            45           141            45
BM_format_to_iterator/<std::deque> C string len = 60                                -0.6481         -0.6471           144            51           143            51
BM_format/string len = 60                                                           -0.0167         -0.0142            73            72            73            72
BM_format_to_back_inserter<std::string>/string len = 60                             -0.0151         -0.0127            73            72            73            72
BM_format_to_back_inserter<std::vector<char>>/string len = 60                       +0.0093         +0.0118            82            82            81            82
BM_format_to_back_inserter<std::deque<char>>/string len = 60                        -0.0003         +0.0023           279           279           279           279
BM_format_to_back_inserter<std::list<char>>/string len = 60                         +0.0025         +0.0050          1177          1180          1174          1180
BM_format_to_iterator/<std::array> string len = 60                                  +0.0046         +0.0070            45            45            44            45
BM_format_to_iterator/<std::string> string len = 60                                 +0.0050         +0.0075            45            45            45            45
BM_format_to_iterator/<std::vector> string len = 60                                 +0.0025         +0.0051            45            45            45            45
BM_format_to_iterator/<std::deque> string len = 60                                  +0.0031         +0.0056            51            51            50            51
BM_format/string_view len = 60                                                      -0.0054         -0.0030            73            72            73            72
BM_format_to_back_inserter<std::string>/string_view len = 60                        +0.0001         +0.0026            73            73            73            73
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60                  -0.0090         -0.0066            83            82            82            82
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60                   +0.0097         +0.0126           280           283           280           283
BM_format_to_back_inserter<std::list<char>>/string_view len = 60                    +0.0011         +0.0036          1176          1177          1173          1177
BM_format_to_iterator/<std::array> string_view len = 60                             +0.0001         +0.0026            44            44            44            44
BM_format_to_iterator/<std::string> string_view len = 60                            +0.0083         +0.0107            45            45            45            45
BM_format_to_iterator/<std::vector> string_view len = 60                            +0.0068         +0.0093            45            45            45            45
BM_format_to_iterator/<std::deque> string_view len = 60                             -0.0038         -0.0014            50            50            50            50
BM_sprintf/C string len = 6000                                                      +2.0230         +2.0305           114           344           114           344
BM_format/C string len = 6000                                                       -0.9169         -0.9167         11792           980         11763           980
BM_format_to_back_inserter<std::string>/C string len = 6000                         -0.9169         -0.9166         11778           979         11746           979
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000                   -0.9194         -0.9192         11715           944         11686           944
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000                    -0.4143         -0.4129         25464         14916         25403         14915
BM_format_to_back_inserter<std::list<char>>/C string len = 6000                     -0.0901         -0.0878        126044        114686        125726        114688
BM_format_to_iterator/<std::array> C string len = 6000                              -0.9852         -0.9852         10792           159         10766           159
BM_format_to_iterator/<std::string> C string len = 6000                             -0.9852         -0.9852         10791           159         10761           159
BM_format_to_iterator/<std::vector> C string len = 6000                             -0.9852         -0.9852         10775           159         10750           159
BM_format_to_iterator/<std::deque> C string len = 6000                              -0.9611         -0.9610         11242           437         11215           437
BM_format/string len = 6000                                                         +0.0108         +0.0133           919           929           917           929
BM_format_to_back_inserter<std::string>/string len = 6000                           +0.0138         +0.0167           920           933           917           933
BM_format_to_back_inserter<std::vector<char>>/string len = 6000                     +0.0041         +0.0064           888           892           886           892
BM_format_to_back_inserter<std::deque<char>>/string len = 6000                      -0.0107         -0.0082         14999         14840         14963         14839
BM_format_to_back_inserter<std::list<char>>/string len = 6000                       +0.0038         +0.0064        114504        114940        114213        114942
BM_format_to_iterator/<std::array> string len = 6000                                +0.2011         +0.2040           120           144           120           144
BM_format_to_iterator/<std::string> string len = 6000                               +0.0032         +0.0057           106           106           106           106
BM_format_to_iterator/<std::vector> string len = 6000                               +0.0057         +0.0085           106           107           106           107
BM_format_to_iterator/<std::deque> string len = 6000                                +0.0011         +0.0036           367           368           366           368
BM_format/string_view len = 6000                                                    +0.0105         +0.0130           910           919           907           919
BM_format_to_back_inserter<std::string>/string_view len = 6000                      +0.0057         +0.0081           911           917           909           917
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000                +0.0023         +0.0050           878           880           876           880
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000                 -0.0118         -0.0094         15031         14854         14994         14853
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000                  +0.0040         +0.0065        114510        114963        114219        114967
BM_format_to_iterator/<std::array> string_view len = 6000                           -0.0299         -0.0275           121           117           120           117
BM_format_to_iterator/<std::string> string_view len = 6000                          +0.0062         +0.0086           116           116           115           116
BM_format_to_iterator/<std::vector> string_view len = 6000                          +0.0034         +0.0062           115           116           115           116
BM_format_to_iterator/<std::deque> string_view len = 6000                           +0.0011         +0.0035           351           351           350           351
OVERALL_GEOMEAN                                                                     -0.2959         -0.2941             0             0             0             0
@mordante mordante requested a review from a team as a code owner August 3, 2024 11:31
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Aug 3, 2024
@llvmbot
Copy link
Member

llvmbot commented Aug 3, 2024

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

This changes the __output_buffer to a new structure. Since the other formatting fucntions std::format_to, std::format_to_n, and std::formatted_size still use the old codepaths the class is in a transition state. At the end of the series the class should be in its final state.

write_double_comparison:

Before

Benchmark Time CPU Iterations

BM_sprintf 197 ns 196 ns 3550000
BM_to_string 218 ns 218 ns 3214000
BM_to_chars 42.4 ns 42.3 ns 16575000
BM_to_chars_as_string 48.2 ns 48.1 ns 14542000
BM_format 175 ns 175 ns 4000000
BM_format_to_back_inserter<std::string> 175 ns 175 ns 3995000
BM_format_to_back_inserter<std::vector<char>> 207 ns 206 ns 3393000
BM_format_to_back_inserter<std::list<char>> 752 ns 750 ns 931000
BM_format_to_iterator/<std::array> 161 ns 161 ns 4345000
BM_format_to_iterator/<std::string> 161 ns 161 ns 4344000
BM_format_to_iterator/<std::vector> 162 ns 161 ns 4344000

After

Benchmark Time CPU Iterations

BM_sprintf 197 ns 197 ns 3550000
BM_to_string 219 ns 219 ns 3199000
BM_to_chars 42.4 ns 42.4 ns 16554000
BM_to_chars_as_string 48.1 ns 48.1 ns 14569000
BM_format 167 ns 167 ns 4203000
BM_format_to_back_inserter<std::string> 179 ns 179 ns 3920000
BM_format_to_back_inserter<std::vector<char>> 214 ns 214 ns 3274000
BM_format_to_back_inserter<std::list<char>> 751 ns 751 ns 930000
BM_format_to_iterator/<std::array> 164 ns 164 ns 4258000
BM_format_to_iterator/<std::string> 165 ns 164 ns 4247000
BM_format_to_iterator/<std::vector> 165 ns 165 ns 4248000

Comparison
Benchmark Time CPU Time Old Time New CPU Old CPU New

BM_sprintf +0.0013 +0.0028 197 197 196 197
BM_to_string +0.0023 +0.0038 218 219 218 219
BM_to_chars +0.0014 +0.0030 42 42 42 42
BM_to_chars_as_string -0.0025 -0.0010 48 48 48 48
BM_format -0.0476 -0.0462 175 167 175 167
BM_format_to_back_inserter<std::string> +0.0190 +0.0205 175 179 175 179
BM_format_to_back_inserter<std::vector<char>> +0.0348 +0.0363 207 214 206 214
BM_format_to_back_inserter<std::list<char>> -0.0013 +0.0005 752 751 750 751
BM_format_to_iterator/<std::array> +0.0188 +0.0203 161 164 161 164
BM_format_to_iterator/<std::string> +0.0207 +0.0226 161 165 161 164
BM_format_to_iterator/<std::vector> +0.0197 +0.0212 162 165 161 165
OVERALL_GEOMEAN +0.0058 +0.0074 0 0 0 0

write_int_comparison:

Before

Benchmark Time CPU Iterations

BM_sprintf 79.6 ns 79.5 ns 8739000
BM_to_string 14.9 ns 14.9 ns 46713000
BM_to_chars 5.68 ns 5.67 ns 120614000
BM_to_chars_as_string 14.2 ns 14.1 ns 49513000
BM_format 69.3 ns 69.2 ns 10105000
BM_format_to_back_inserter<std::string> 69.2 ns 69.1 ns 10138000
BM_format_to_back_inserter<std::vector<char>> 90.6 ns 90.5 ns 7728000
BM_format_to_back_inserter<std::list<char>> 234 ns 234 ns 2986000
BM_format_to_iterator/<std::array> 59.3 ns 59.3 ns 11805000
BM_format_to_iterator/<std::string> 58.7 ns 58.6 ns 11943000
BM_format_to_iterator/<std::vector> 60.1 ns 60.1 ns 11670000

After

Benchmark Time CPU Iterations

BM_sprintf 80.2 ns 80.2 ns 8670000
BM_to_string 15.0 ns 15.0 ns 46559000
BM_to_chars 4.93 ns 4.93 ns 138016000
BM_to_chars_as_string 15.4 ns 15.4 ns 45415000
BM_format 62.1 ns 62.0 ns 11316000
BM_format_to_back_inserter<std::string> 70.2 ns 70.2 ns 9962000
BM_format_to_back_inserter<std::vector<char>> 92.8 ns 92.8 ns 7544000
BM_format_to_back_inserter<std::list<char>> 240 ns 240 ns 2917000
BM_format_to_iterator/<std::array> 60.5 ns 60.5 ns 11572000
BM_format_to_iterator/<std::string> 60.2 ns 60.2 ns 11653000
BM_format_to_iterator/<std::vector> 60.1 ns 60.1 ns 11659000

Comparison
Benchmark Time CPU Time Old Time New CPU Old CPU New

BM_sprintf +0.0072 +0.0081 80 80 80 80
BM_to_string +0.0043 +0.0053 15 15 15 15
BM_to_chars -0.1324 -0.1316 6 5 6 5
BM_to_chars_as_string +0.0895 +0.0906 14 15 14 15
BM_format -0.1047 -0.1040 69 62 69 62
BM_format_to_back_inserter<std::string> +0.0148 +0.0157 69 70 69 70
BM_format_to_back_inserter<std::vector<char>> +0.0241 +0.0251 91 93 90 93
BM_format_to_back_inserter<std::list<char>> +0.0222 +0.0232 234 240 234 240
BM_format_to_iterator/<std::array> +0.0196 +0.0205 59 60 59 60
BM_format_to_iterator/<std::string> +0.0266 +0.0275 59 60 59 60
BM_format_to_iterator/<std::vector> -0.0004 +0.0005 60 60 60 60
OVERALL_GEOMEAN -0.0045 -0.0036 0 0 0 0

write_string_comparison:

Before

Benchmark Time CPU Iterations

BM_sprintf/C string len = 6 4.82 ns 4.82 ns 145548481
BM_format/C string len = 6 55.1 ns 55.1 ns 12713693
BM_format_to_back_inserter<std::string>/C string len = 6 55.1 ns 55.1 ns 12690821
BM_format_to_back_inserter<std::vector<char>>/C string len = 6 71.5 ns 71.5 ns 9805550
BM_format_to_back_inserter<std::deque<char>>/C string len = 6 154 ns 154 ns 4536256
BM_format_to_back_inserter<std::list<char>>/C string len = 6 130 ns 130 ns 5348845
BM_format_to_iterator/<std::array> C string len = 6 44.9 ns 44.9 ns 15556175
BM_format_to_iterator/<std::string> C string len = 6 45.8 ns 45.8 ns 15290662
BM_format_to_iterator/<std::vector> C string len = 6 44.4 ns 44.4 ns 15807704
BM_format_to_iterator/<std::deque> C string len = 6 50.0 ns 50.0 ns 13973893
BM_format/string len = 6 54.7 ns 54.7 ns 12793406
BM_format_to_back_inserter<std::string>/string len = 6 55.5 ns 55.5 ns 12620370
BM_format_to_back_inserter<std::vector<char>>/string len = 6 70.4 ns 70.4 ns 9936490
BM_format_to_back_inserter<std::deque<char>>/string len = 6 155 ns 155 ns 4521357
BM_format_to_back_inserter<std::list<char>>/string len = 6 135 ns 135 ns 5201519
BM_format_to_iterator/<std::array> string len = 6 44.6 ns 44.6 ns 15703872
BM_format_to_iterator/<std::string> string len = 6 45.0 ns 45.0 ns 15545182
BM_format_to_iterator/<std::vector> string len = 6 45.0 ns 45.0 ns 15539130
BM_format_to_iterator/<std::deque> string len = 6 50.5 ns 50.5 ns 13846916
BM_format/string_view len = 6 54.6 ns 54.6 ns 12821301
BM_format_to_back_inserter<std::string>/string_view len = 6 54.6 ns 54.6 ns 12827673
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6 69.9 ns 69.9 ns 9958365
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6 157 ns 157 ns 4462445
BM_format_to_back_inserter<std::list<char>>/string_view len = 6 134 ns 134 ns 5232155
BM_format_to_iterator/<std::array> string_view len = 6 44.2 ns 44.2 ns 15871362
BM_format_to_iterator/<std::string> string_view len = 6 45.0 ns 45.0 ns 15582582
BM_format_to_iterator/<std::vector> string_view len = 6 45.1 ns 45.1 ns 15539906
BM_format_to_iterator/<std::deque> string_view len = 6 50.5 ns 50.5 ns 13896524
BM_sprintf/C string len = 60 4.15 ns 4.15 ns 168165776
BM_format/C string len = 60 73.8 ns 73.8 ns 9498291
BM_format_to_back_inserter<std::string>/C string len = 60 73.6 ns 73.6 ns 9535890
BM_format_to_back_inserter<std::vector<char>>/C string len = 60 83.1 ns 83.1 ns 8428154
BM_format_to_back_inserter<std::deque<char>>/C string len = 60 281 ns 281 ns 2490093
BM_format_to_back_inserter<std::list<char>>/C string len = 60 1157 ns 1157 ns 605227
BM_format_to_iterator/<std::array> C string len = 60 44.9 ns 44.9 ns 15604442
BM_format_to_iterator/<std::string> C string len = 60 45.8 ns 45.8 ns 15272196
BM_format_to_iterator/<std::vector> C string len = 60 44.6 ns 44.7 ns 15683193
BM_format_to_iterator/<std::deque> C string len = 60 50.6 ns 50.6 ns 13698382
BM_format/string len = 60 72.3 ns 72.3 ns 9648955
BM_format_to_back_inserter<std::string>/string len = 60 72.0 ns 72.0 ns 9738373
BM_format_to_back_inserter<std::vector<char>>/string len = 60 82.3 ns 82.3 ns 8517896
BM_format_to_back_inserter<std::deque<char>>/string len = 60 280 ns 280 ns 2496054
BM_format_to_back_inserter<std::list<char>>/string len = 60 1162 ns 1162 ns 602383
BM_format_to_iterator/<std::array> string len = 60 44.5 ns 44.5 ns 15727799
BM_format_to_iterator/<std::string> string len = 60 49.6 ns 49.6 ns 14096012
BM_format_to_iterator/<std::vector> string len = 60 49.8 ns 49.8 ns 14053734
BM_format_to_iterator/<std::deque> string len = 60 50.8 ns 50.8 ns 13801448
BM_format/string_view len = 60 72.5 ns 72.5 ns 9653638
BM_format_to_back_inserter<std::string>/string_view len = 60 72.7 ns 72.7 ns 9598203
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60 81.9 ns 81.9 ns 8522306
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60 283 ns 283 ns 2475014
BM_format_to_back_inserter<std::list<char>>/string_view len = 60 1162 ns 1162 ns 600924
BM_format_to_iterator/<std::array> string_view len = 60 44.1 ns 44.1 ns 15858951
BM_format_to_iterator/<std::string> string_view len = 60 44.9 ns 44.9 ns 15579340
BM_format_to_iterator/<std::vector> string_view len = 60 44.9 ns 44.9 ns 15586711
BM_format_to_iterator/<std::deque> string_view len = 60 50.0 ns 50.0 ns 13980804
BM_sprintf/C string len = 6000 116 ns 116 ns 6051541
BM_format/C string len = 6000 1000 ns 1000 ns 698647
BM_format_to_back_inserter<std::string>/C string len = 6000 1002 ns 1002 ns 701440
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000 956 ns 956 ns 727585
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000 14898 ns 14898 ns 46994
BM_format_to_back_inserter<std::list<char>>/C string len = 6000 114860 ns 114859 ns 6106
BM_format_to_iterator/<std::array> C string len = 6000 158 ns 158 ns 4425133
BM_format_to_iterator/<std::string> C string len = 6000 161 ns 161 ns 4335471
BM_format_to_iterator/<std::vector> C string len = 6000 157 ns 157 ns 4444174
BM_format_to_iterator/<std::deque> C string len = 6000 445 ns 445 ns 1574120
BM_format/string len = 6000 929 ns 929 ns 753630
BM_format_to_back_inserter<std::string>/string len = 6000 930 ns 930 ns 752888
BM_format_to_back_inserter<std::vector<char>>/string len = 6000 910 ns 910 ns 771111
BM_format_to_back_inserter<std::deque<char>>/string len = 6000 14875 ns 14876 ns 47221
BM_format_to_back_inserter<std::list<char>>/string len = 6000 114937 ns 114936 ns 6092
BM_format_to_iterator/<std::array> string len = 6000 118 ns 118 ns 5963643
BM_format_to_iterator/<std::string> string len = 6000 106 ns 106 ns 6584711
BM_format_to_iterator/<std::vector> string len = 6000 106 ns 106 ns 6583118
BM_format_to_iterator/<std::deque> string len = 6000 391 ns 391 ns 1790538
BM_format/string_view len = 6000 935 ns 935 ns 744348
BM_format_to_back_inserter<std::string>/string_view len = 6000 934 ns 934 ns 742039
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000 895 ns 895 ns 783527
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000 14864 ns 14865 ns 47122
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000 115042 ns 115044 ns 6091
BM_format_to_iterator/<std::array> string_view len = 6000 115 ns 115 ns 6070197
BM_format_to_iterator/<std::string> string_view len = 6000 116 ns 116 ns 6035109
BM_format_to_iterator/<std::vector> string_view len = 6000 115 ns 115 ns 6067683
BM_format_to_iterator/<std::deque> string_view len = 6000 387 ns 387 ns 1803466

After

Benchmark Time CPU Iterations

BM_sprintf/C string len = 6 3.56 ns 3.56 ns 196337806
BM_format/C string len = 6 49.1 ns 49.1 ns 14241174
BM_format_to_back_inserter<std::string>/C string len = 6 56.8 ns 56.8 ns 12341483
BM_format_to_back_inserter<std::vector<char>>/C string len = 6 72.9 ns 72.9 ns 9610864
BM_format_to_back_inserter<std::deque<char>>/C string len = 6 155 ns 155 ns 4528719
BM_format_to_back_inserter<std::list<char>>/C string len = 6 137 ns 137 ns 5103340
BM_format_to_iterator/<std::array> C string len = 6 46.4 ns 46.4 ns 15081626
BM_format_to_iterator/<std::string> C string len = 6 47.0 ns 47.0 ns 14893458
BM_format_to_iterator/<std::vector> C string len = 6 45.9 ns 45.9 ns 15243762
BM_format_to_iterator/<std::deque> C string len = 6 52.6 ns 52.6 ns 13323560
BM_format/string len = 6 49.3 ns 49.3 ns 14181485
BM_format_to_back_inserter<std::string>/string len = 6 55.4 ns 55.4 ns 12644078
BM_format_to_back_inserter<std::vector<char>>/string len = 6 72.7 ns 72.7 ns 9618696
BM_format_to_back_inserter<std::deque<char>>/string len = 6 154 ns 154 ns 4540873
BM_format_to_back_inserter<std::list<char>>/string len = 6 134 ns 134 ns 5220153
BM_format_to_iterator/<std::array> string len = 6 46.5 ns 46.5 ns 15064445
BM_format_to_iterator/<std::string> string len = 6 47.3 ns 47.3 ns 14786851
BM_format_to_iterator/<std::vector> string len = 6 46.5 ns 46.5 ns 15069381
BM_format_to_iterator/<std::deque> string len = 6 52.9 ns 52.9 ns 13207437
BM_format/string_view len = 6 47.6 ns 47.6 ns 14688449
BM_format_to_back_inserter<std::string>/string_view len = 6 56.1 ns 56.1 ns 12514239
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6 72.0 ns 72.0 ns 9705591
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6 152 ns 152 ns 4607470
BM_format_to_back_inserter<std::list<char>>/string_view len = 6 134 ns 134 ns 5233005
BM_format_to_iterator/<std::array> string_view len = 6 46.0 ns 46.0 ns 15205542
BM_format_to_iterator/<std::string> string_view len = 6 46.5 ns 46.5 ns 15067775
BM_format_to_iterator/<std::vector> string_view len = 6 46.5 ns 46.5 ns 15057288
BM_format_to_iterator/<std::deque> string_view len = 6 51.8 ns 51.8 ns 13564649
BM_sprintf/C string len = 60 4.83 ns 4.83 ns 145020116
BM_format/C string len = 60 72.3 ns 72.3 ns 9665555
BM_format_to_back_inserter<std::string>/C string len = 60 85.0 ns 85.0 ns 8249050
BM_format_to_back_inserter<std::vector<char>>/C string len = 60 94.7 ns 94.7 ns 7398143
BM_format_to_back_inserter<std::deque<char>>/C string len = 60 286 ns 286 ns 2452225
BM_format_to_back_inserter<std::list<char>>/C string len = 60 1179 ns 1179 ns 595011
BM_format_to_iterator/<std::array> C string len = 60 46.1 ns 46.1 ns 15157525
BM_format_to_iterator/<std::string> C string len = 60 47.0 ns 47.0 ns 14899863
BM_format_to_iterator/<std::vector> C string len = 60 45.8 ns 45.8 ns 15272542
BM_format_to_iterator/<std::deque> C string len = 60 58.7 ns 58.7 ns 11958910
BM_format/string len = 60 61.7 ns 61.7 ns 11308865
BM_format_to_back_inserter<std::string>/string len = 60 74.2 ns 74.2 ns 9401855
BM_format_to_back_inserter<std::vector<char>>/string len = 60 86.6 ns 86.6 ns 8079197
BM_format_to_back_inserter<std::deque<char>>/string len = 60 278 ns 278 ns 2519254
BM_format_to_back_inserter<std::list<char>>/string len = 60 1169 ns 1170 ns 597703
BM_format_to_iterator/<std::array> string len = 60 46.4 ns 46.4 ns 15074759
BM_format_to_iterator/<std::string> string len = 60 47.3 ns 47.3 ns 14801107
BM_format_to_iterator/<std::vector> string len = 60 46.3 ns 46.4 ns 15085548
BM_format_to_iterator/<std::deque> string len = 60 52.2 ns 52.2 ns 13331015
BM_format/string_view len = 60 65.0 ns 65.0 ns 10756847
BM_format_to_back_inserter<std::string>/string_view len = 60 78.5 ns 78.5 ns 9051370
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60 87.9 ns 87.9 ns 7946825
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60 280 ns 280 ns 2505999
BM_format_to_back_inserter<std::list<char>>/string_view len = 60 1174 ns 1174 ns 594829
BM_format_to_iterator/<std::array> string_view len = 60 46.3 ns 46.3 ns 15149785
BM_format_to_iterator/<std::string> string_view len = 60 46.7 ns 46.7 ns 15002678
BM_format_to_iterator/<std::vector> string_view len = 60 46.7 ns 46.7 ns 14996445
BM_format_to_iterator/<std::deque> string_view len = 60 52.6 ns 52.6 ns 13255470
BM_sprintf/C string len = 6000 77.1 ns 77.1 ns 9099121
BM_format/C string len = 6000 350 ns 350 ns 2013049
BM_format_to_back_inserter<std::string>/C string len = 6000 992 ns 992 ns 709093
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000 1016 ns 1016 ns 694784
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000 15158 ns 15159 ns 46125
BM_format_to_back_inserter<std::list<char>>/C string len = 6000 115703 ns 115705 ns 6055
BM_format_to_iterator/<std::array> C string len = 6000 166 ns 166 ns 4224749
BM_format_to_iterator/<std::string> C string len = 6000 153 ns 153 ns 4573034
BM_format_to_iterator/<std::vector> C string len = 6000 150 ns 150 ns 4678898
BM_format_to_iterator/<std::deque> C string len = 6000 465 ns 465 ns 1506323
BM_format/string len = 6000 281 ns 281 ns 2462572
BM_format_to_back_inserter<std::string>/string len = 6000 935 ns 935 ns 745376
BM_format_to_back_inserter<std::vector<char>>/string len = 6000 939 ns 939 ns 747498
BM_format_to_back_inserter<std::deque<char>>/string len = 6000 15069 ns 15069 ns 46429
BM_format_to_back_inserter<std::list<char>>/string len = 6000 115537 ns 115539 ns 6063
BM_format_to_iterator/<std::array> string len = 6000 120 ns 120 ns 5849159
BM_format_to_iterator/<std::string> string len = 6000 108 ns 108 ns 6482306
BM_format_to_iterator/<std::vector> string len = 6000 107 ns 107 ns 6547915
BM_format_to_iterator/<std::deque> string len = 6000 397 ns 397 ns 1763729
BM_format/string_view len = 6000 282 ns 282 ns 2490133
BM_format_to_back_inserter<std::string>/string_view len = 6000 927 ns 927 ns 750931
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000 946 ns 946 ns 735544
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000 15028 ns 15029 ns 46612
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000 115153 ns 115153 ns 6057
BM_format_to_iterator/<std::array> string_view len = 6000 122 ns 122 ns 5753940
BM_format_to_iterator/<std::string> string_view len = 6000 108 ns 108 ns 6507555
BM_format_to_iterator/<std::vector> string_view len = 6000 107 ns 107 ns 6510450
BM_format_to_iterator/<std::deque> string_view len = 6000 398 ns 398 ns 1762517

Comparison
Benchmark Time CPU Time Old Time New CPU Old CPU New

BM_sprintf/C string len = 6 -0.2599 -0.2599 5 4 5 4
BM_format/C string len = 6 -0.1094 -0.1095 55 49 55 49
BM_format_to_back_inserter<std::string>/C string len = 6 +0.0316 +0.0316 55 57 55 57
BM_format_to_back_inserter<std::vector<char>>/C string len = 6 +0.0204 +0.0204 71 73 71 73
BM_format_to_back_inserter<std::deque<char>>/C string len = 6 +0.0023 +0.0023 154 155 154 155
BM_format_to_back_inserter<std::list<char>>/C string len = 6 +0.0521 +0.0520 130 137 130 137
BM_format_to_iterator/<std::array> C string len = 6 +0.0317 +0.0317 45 46 45 46
BM_format_to_iterator/<std::string> C string len = 6 +0.0265 +0.0265 46 47 46 47
BM_format_to_iterator/<std::vector> C string len = 6 +0.0345 +0.0345 44 46 44 46
BM_format_to_iterator/<std::deque> C string len = 6 +0.0511 +0.0511 50 53 50 53
BM_format/string len = 6 -0.0981 -0.0981 55 49 55 49
BM_format_to_back_inserter<std::string>/string len = 6 -0.0028 -0.0028 56 55 56 55
BM_format_to_back_inserter<std::vector<char>>/string len = 6 +0.0331 +0.0331 70 73 70 73
BM_format_to_back_inserter<std::deque<char>>/string len = 6 -0.0040 -0.0040 155 154 155 154
BM_format_to_back_inserter<std::list<char>>/string len = 6 -0.0019 -0.0019 135 134 135 134
BM_format_to_iterator/<std::array> string len = 6 +0.0427 +0.0427 45 46 45 46
BM_format_to_iterator/<std::string> string len = 6 +0.0515 +0.0515 45 47 45 47
BM_format_to_iterator/<std::vector> string len = 6 +0.0316 +0.0316 45 46 45 46
BM_format_to_iterator/<std::deque> string len = 6 +0.0475 +0.0475 51 53 51 53
BM_format/string_view len = 6 -0.1267 -0.1267 55 48 55 48
BM_format_to_back_inserter<std::string>/string_view len = 6 +0.0283 +0.0283 55 56 55 56
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6 +0.0291 +0.0291 70 72 70 72
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6 -0.0305 -0.0306 157 152 157 152
BM_format_to_back_inserter<std::list<char>>/string_view len = 6 -0.0012 -0.0012 134 134 134 134
BM_format_to_iterator/<std::array> string_view len = 6 +0.0426 +0.0426 44 46 44 46
BM_format_to_iterator/<std::string> string_view len = 6 +0.0322 +0.0322 45 46 45 46
BM_format_to_iterator/<std::vector> string_view len = 6 +0.0309 +0.0309 45 46 45 46
BM_format_to_iterator/<std::deque> string_view len = 6 +0.0248 +0.0248 51 52 51 52
BM_sprintf/C string len = 60 +0.1633 +0.1633 4 5 4 5
BM_format/C string len = 60 -0.0203 -0.0203 74 72 74 72
BM_format_to_back_inserter<std::string>/C string len = 60 +0.1548 +0.1548 74 85 74 85
BM_format_to_back_inserter<std::vector<char>>/C string len = 60 +0.1395 +0.1395 83 95 83 95
BM_format_to_back_inserter<std::deque<char>>/C string len = 60 +0.0157 +0.0157 281 286 281 286
BM_format_to_back_inserter<std::list<char>>/C string len = 60 +0.0191 +0.0191 1157 1179 1157 1179
BM_format_to_iterator/<std::array> C string len = 60 +0.0283 +0.0283 45 46 45 46
BM_format_to_iterator/<std::string> C string len = 60 +0.0251 +0.0252 46 47 46 47
BM_format_to_iterator/<std::vector> C string len = 60 +0.0263 +0.0263 45 46 45 46
BM_format_to_iterator/<std::deque> C string len = 60 +0.1592 +0.1591 51 59 51 59
BM_format/string len = 60 -0.1466 -0.1466 72 62 72 62
BM_format_to_back_inserter<std::string>/string len = 60 +0.0299 +0.0299 72 74 72 74
BM_format_to_back_inserter<std::vector<char>>/string len = 60 +0.0522 +0.0522 82 87 82 87
BM_format_to_back_inserter<std::deque<char>>/string len = 60 -0.0099 -0.0099 280 278 280 278
BM_format_to_back_inserter<std::list<char>>/string len = 60 +0.0062 +0.0062 1162 1169 1162 1170
BM_format_to_iterator/<std::array> string len = 60 +0.0430 +0.0430 45 46 45 46
BM_format_to_iterator/<std::string> string len = 60 -0.0466 -0.0466 50 47 50 47
BM_format_to_iterator/<std::vector> string len = 60 -0.0693 -0.0693 50 46 50 46
BM_format_to_iterator/<std::deque> string len = 60 +0.0275 +0.0275 51 52 51 52
BM_format/string_view len = 60 -0.1034 -0.1034 73 65 73 65
BM_format_to_back_inserter<std::string>/string_view len = 60 +0.0790 +0.0790 73 78 73 78
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60 +0.0735 +0.0735 82 88 82 88
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60 -0.0103 -0.0104 283 280 283 280
BM_format_to_back_inserter<std::list<char>>/string_view len = 60 +0.0101 +0.0101 1162 1174 1162 1174
BM_format_to_iterator/<std::array> string_view len = 60 +0.0484 +0.0484 44 46 44 46
BM_format_to_iterator/<std::string> string_view len = 60 +0.0387 +0.0387 45 47 45 47
BM_format_to_iterator/<std::vector> string_view len = 60 +0.0402 +0.0402 45 47 45 47
BM_format_to_iterator/<std::deque> string_view len = 60 +0.0508 +0.0508 50 53 50 53
BM_sprintf/C string len = 6000 -0.3337 -0.3337 116 77 116 77
BM_format/C string len = 6000 -0.6500 -0.6500 1000 350 1000 350
BM_format_to_back_inserter<std::string>/C string len = 6000 -0.0104 -0.0105 1002 992 1002 992
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000 +0.0630 +0.0630 956 1016 956 1016
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000 +0.0175 +0.0175 14898 15158 14898 15159
BM_format_to_back_inserter<std::list<char>>/C string len = 6000 +0.0073 +0.0074 114860 115703 114859 115705
BM_format_to_iterator/<std::array> C string len = 6000 +0.0504 +0.0504 158 166 158 166
BM_format_to_iterator/<std::string> C string len = 6000 -0.0486 -0.0486 161 153 161 153
BM_format_to_iterator/<std::vector> C string len = 6000 -0.0483 -0.0483 157 150 157 150
BM_format_to_iterator/<std::deque> C string len = 6000 +0.0459 +0.0459 445 465 445 465
BM_format/string len = 6000 -0.6975 -0.6975 929 281 929 281
BM_format_to_back_inserter<std::string>/string len = 6000 +0.0050 +0.0050 930 935 930 935
BM_format_to_back_inserter<std::vector<char>>/string len = 6000 +0.0321 +0.0322 910 939 910 939
BM_format_to_back_inserter<std::deque<char>>/string len = 6000 +0.0130 +0.0130 14875 15069 14876 15069
BM_format_to_back_inserter<std::list<char>>/string len = 6000 +0.0052 +0.0052 114937 115537 114936 115539
BM_format_to_iterator/<std::array> string len = 6000 +0.0211 +0.0211 118 120 118 120
BM_format_to_iterator/<std::string> string len = 6000 +0.0146 +0.0146 106 108 106 108
BM_format_to_iterator/<std::vector> string len = 6000 +0.0048 +0.0048 106 107 106 107
BM_format_to_iterator/<std::deque> string len = 6000 +0.0150 +0.0150 391 397 391 397
BM_format/string_view len = 6000 -0.6989 -0.6989 935 282 935 282
BM_format_to_back_inserter<std::string>/string_view len = 6000 -0.0083 -0.0083 934 927 934 927
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000 +0.0566 +0.0566 895 946 895 946
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000 +0.0111 +0.0110 14864 15028 14865 15029
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000 +0.0010 +0.0009 115042 115153 115044 115153
BM_format_to_iterator/<std::array> string_view len = 6000 +0.0560 +0.0560 115 122 115 122
BM_format_to_iterator/<std::string> string_view len = 6000 -0.0693 -0.0693 116 108 116 108
BM_format_to_iterator/<std::vector> string_view len = 6000 -0.0703 -0.0703 115 107 115 107
BM_format_to_iterator/<std::deque> string_view len = 6000 +0.0271 +0.0271 387 398 387 398
OVERALL_GEOMEAN -0.0350 -0.0350 0 0 0 0

format:
Before

Benchmark Time CPU Iterations UserCounters...

BM_format_string<char>/1 55.5 ns 55.5 ns 12463288 bytes_per_second=17.187Mi/s
BM_format_string<char>/2 27.6 ns 27.6 ns 25421994 bytes_per_second=69.1874Mi/s
BM_format_string<char>/4 14.0 ns 14.0 ns 49785656 bytes_per_second=271.524Mi/s
BM_format_string<char>/8 7.07 ns 7.07 ns 99247048 bytes_per_second=1.05444Gi/s
BM_format_string<char>/16 3.53 ns 3.53 ns 198072224 bytes_per_second=4.21726Gi/s
BM_format_string<char>/32 2.31 ns 2.31 ns 302771136 bytes_per_second=12.9138Gi/s
BM_format_string<char>/64 1.15 ns 1.15 ns 606646976 bytes_per_second=51.7527Gi/s
BM_format_string<char>/128 0.597 ns 0.597 ns 1172263936 bytes_per_second=199.688Gi/s
BM_format_string<char>/256 0.327 ns 0.327 ns 2148927744 bytes_per_second=728.678Gi/s
BM_format_string<char>/512 0.248 ns 0.248 ns 2821635584 bytes_per_second=1.8779Ti/s
BM_format_string<char>/1024 0.203 ns 0.203 ns 3433579520 bytes_per_second=4.57798Ti/s
BM_format_string<char>/2048 0.164 ns 0.164 ns 4277524480 bytes_per_second=11.3793Ti/s
BM_format_string<char>/4096 0.137 ns 0.137 ns 5122269184 bytes_per_second=27.2589Ti/s
BM_format_string<char>/8192 0.126 ns 0.126 ns 5564243968 bytes_per_second=59.2812Ti/s
BM_format_string<char>/16384 0.136 ns 0.136 ns 5153013760 bytes_per_second=109.492Ti/s
BM_format_string<char>/32768 0.135 ns 0.135 ns 5165088768 bytes_per_second=219.985Ti/s
BM_format_string<char>/65536 0.243 ns 0.242 ns 2930180096 bytes_per_second=246.57Ti/s
BM_format_string<char>/131072 0.490 ns 0.489 ns 1437990912 bytes_per_second=243.75Ti/s
BM_format_string<char>/262144 0.593 ns 0.592 ns 1183055872 bytes_per_second=402.931Ti/s
BM_format_string<char>/524288 0.643 ns 0.641 ns 1092616192 bytes_per_second=743.445Ti/s
BM_format_string<char>/1048576 0.669 ns 0.668 ns 1045430272 bytes_per_second=1.39478Pi/s
BM_format_string<wchar_t>/1 56.0 ns 55.9 ns 12511543 bytes_per_second=68.2628Mi/s
BM_format_string<wchar_t>/2 28.0 ns 27.9 ns 25062366 bytes_per_second=273.519Mi/s
BM_format_string<wchar_t>/4 14.0 ns 14.0 ns 50257068 bytes_per_second=1.06742Gi/s
BM_format_string<wchar_t>/8 9.24 ns 9.21 ns 76118616 bytes_per_second=3.23473Gi/s
BM_format_string<wchar_t>/16 4.66 ns 4.65 ns 151420352 bytes_per_second=12.8261Gi/s
BM_format_string<wchar_t>/32 2.35 ns 2.35 ns 298417600 bytes_per_second=50.7972Gi/s
BM_format_string<wchar_t>/64 1.35 ns 1.34 ns 521608704 bytes_per_second=177.502Gi/s
BM_format_string<wchar_t>/128 1.03 ns 1.03 ns 680946304 bytes_per_second=463.91Gi/s
BM_format_string<wchar_t>/256 0.849 ns 0.847 ns 825871104 bytes_per_second=1.09901Ti/s
BM_format_string<wchar_t>/512 0.681 ns 0.679 ns 1033245696 bytes_per_second=2.74383Ti/s
BM_format_string<wchar_t>/1024 0.576 ns 0.575 ns 1219777536 bytes_per_second=6.48343Ti/s
BM_format_string<wchar_t>/2048 0.515 ns 0.514 ns 1361629184 bytes_per_second=14.4881Ti/s
BM_format_string<wchar_t>/4096 0.546 ns 0.545 ns 1285427200 bytes_per_second=27.3342Ti/s
BM_format_string<wchar_t>/8192 0.550 ns 0.548 ns 1277042688 bytes_per_second=54.3343Ti/s
BM_format_string<wchar_t>/16384 0.583 ns 0.581 ns 1203879936 bytes_per_second=102.544Ti/s
BM_format_string<wchar_t>/32768 0.640 ns 0.638 ns 1095139328 bytes_per_second=186.82Ti/s
BM_format_string<wchar_t>/65536 0.642 ns 0.640 ns 1093337088 bytes_per_second=372.283Ti/s
BM_format_string<wchar_t>/131072 0.655 ns 0.654 ns 1070596096 bytes_per_second=729.428Ti/s
BM_format_string<wchar_t>/262144 2.68 ns 2.67 ns 262406144 bytes_per_second=357.446Ti/s
BM_format_string<wchar_t>/524288 2.13 ns 2.13 ns 330301440 bytes_per_second=897.574Ti/s
BM_format_string<wchar_t>/1048576 2.44 ns 2.43 ns 288358400 bytes_per_second=1.53149Pi/s

After

Benchmark Time CPU Iterations UserCounters...

BM_format_string<char>/1 49.3 ns 49.1 ns 14230742 bytes_per_second=19.4054Mi/s
BM_format_string<char>/2 24.8 ns 24.8 ns 28253114 bytes_per_second=77.0465Mi/s
BM_format_string<char>/4 12.4 ns 12.4 ns 56381440 bytes_per_second=307.462Mi/s
BM_format_string<char>/8 6.23 ns 6.21 ns 112951232 bytes_per_second=1.19924Gi/s
BM_format_string<char>/16 3.10 ns 3.09 ns 225822496 bytes_per_second=4.81566Gi/s
BM_format_string<char>/32 1.98 ns 1.98 ns 354208192 bytes_per_second=15.0825Gi/s
BM_format_string<char>/64 0.990 ns 0.987 ns 714296384 bytes_per_second=60.3689Gi/s
BM_format_string<char>/128 0.504 ns 0.503 ns 1399988480 bytes_per_second=237.144Gi/s
BM_format_string<char>/256 0.335 ns 0.334 ns 2084828928 bytes_per_second=712.859Gi/s
BM_format_string<char>/512 0.187 ns 0.186 ns 3760082432 bytes_per_second=2.50102Ti/s
BM_format_string<char>/1024 0.109 ns 0.108 ns 6455339008 bytes_per_second=8.59552Ti/s
BM_format_string<char>/2048 0.080 ns 0.080 ns 8754006016 bytes_per_second=23.2731Ti/s
BM_format_string<char>/4096 0.051 ns 0.051 ns 13786701824 bytes_per_second=73.4088Ti/s
BM_format_string<char>/8192 0.042 ns 0.042 ns 16851435520 bytes_per_second=178.737Ti/s
BM_format_string<char>/16384 0.122 ns 0.122 ns 5746589696 bytes_per_second=122.029Ti/s
BM_format_string<char>/32768 0.107 ns 0.106 ns 6571687936 bytes_per_second=280.122Ti/s
BM_format_string<char>/65536 0.102 ns 0.102 ns 6876626944 bytes_per_second=584.381Ti/s
BM_format_string<char>/131072 0.106 ns 0.105 ns 6643122176 bytes_per_second=1.10413Pi/s
BM_format_string<char>/262144 0.589 ns 0.587 ns 1189609472 bytes_per_second=406.438Ti/s
BM_format_string<char>/524288 0.644 ns 0.642 ns 1088946176 bytes_per_second=743.064Ti/s
BM_format_string<char>/1048576 0.672 ns 0.670 ns 1039138816 bytes_per_second=1.38968Pi/s
BM_format_string<wchar_t>/1 48.7 ns 48.6 ns 14423178 bytes_per_second=78.5263Mi/s
BM_format_string<wchar_t>/2 24.4 ns 24.3 ns 28831748 bytes_per_second=313.869Mi/s
BM_format_string<wchar_t>/4 12.2 ns 12.2 ns 57661220 bytes_per_second=1.2253Gi/s
BM_format_string<wchar_t>/8 7.81 ns 7.79 ns 89887592 bytes_per_second=3.82675Gi/s
BM_format_string<wchar_t>/16 3.88 ns 3.87 ns 180450176 bytes_per_second=15.418Gi/s
BM_format_string<wchar_t>/32 1.98 ns 1.98 ns 354046112 bytes_per_second=60.3262Gi/s
BM_format_string<wchar_t>/64 1.02 ns 1.01 ns 689511680 bytes_per_second=234.906Gi/s
BM_format_string<wchar_t>/128 0.577 ns 0.576 ns 1215361408 bytes_per_second=828.297Gi/s
BM_format_string<wchar_t>/256 0.804 ns 0.802 ns 872249088 bytes_per_second=1.16111Ti/s
BM_format_string<wchar_t>/512 0.642 ns 0.641 ns 1093858304 bytes_per_second=2.90766Ti/s
BM_format_string<wchar_t>/1024 0.517 ns 0.516 ns 1354798080 bytes_per_second=7.21845Ti/s
BM_format_string<wchar_t>/2048 0.469 ns 0.467 ns 1491910656 bytes_per_second=15.9386Ti/s
BM_format_string<wchar_t>/4096 0.794 ns 0.792 ns 883822592 bytes_per_second=18.8156Ti/s
BM_format_string<wchar_t>/8192 0.722 ns 0.720 ns 971718656 bytes_per_second=41.3996Ti/s
BM_format_string<wchar_t>/16384 0.703 ns 0.701 ns 998031360 bytes_per_second=85.0369Ti/s
BM_format_string<wchar_t>/32768 0.724 ns 0.720 ns 971538432 bytes_per_second=165.467Ti/s
BM_format_string<wchar_t>/65536 0.745 ns 0.744 ns 941228032 bytes_per_second=320.665Ti/s
BM_format_string<wchar_t>/131072 0.742 ns 0.740 ns 945422336 bytes_per_second=644.032Ti/s
BM_format_string<wchar_t>/262144 2.99 ns 2.98 ns 234881024 bytes_per_second=319.75Ti/s
BM_format_string<wchar_t>/524288 3.31 ns 3.30 ns 212860928 bytes_per_second=578.085Ti/s
BM_format_string<wchar_t>/1048576 2.69 ns 2.68 ns 260046848 bytes_per_second=1.39081Pi/s

Comparison
Benchmark Time CPU Time Old Time New CPU Old CPU New

BM_format_string<char>/1 -0.1122 -0.1143 55 49 55 49
BM_format_string<char>/2 -0.0999 -0.1020 28 25 28 25
BM_format_string<char>/4 -0.1148 -0.1169 14 12 14 12
BM_format_string<char>/8 -0.1186 -0.1207 7 6 7 6
BM_format_string<char>/16 -0.1222 -0.1243 4 3 4 3
BM_format_string<char>/32 -0.1417 -0.1438 2 2 2 2
BM_format_string<char>/64 -0.1407 -0.1427 1 1 1 1
BM_format_string<char>/128 -0.1559 -0.1579 1 1 1 1
BM_format_string<char>/256 +0.0249 +0.0222 0 0 0 0
BM_format_string<char>/512 -0.2473 -0.2491 0 0 0 0
BM_format_string<char>/1024 -0.4661 -0.4674 0 0 0 0
BM_format_string<char>/2048 -0.5096 -0.5111 0 0 0 0
BM_format_string<char>/4096 -0.6278 -0.6287 0 0 0 0
BM_format_string<char>/8192 -0.6674 -0.6683 0 0 0 0
BM_format_string<char>/16384 -0.1005 -0.1027 0 0 0 0
BM_format_string<char>/32768 -0.2127 -0.2147 0 0 0 0
BM_format_string<char>/65536 -0.5796 -0.5781 0 0 0 0
BM_format_string<char>/131072 -0.7844 -0.7844 0 0 0 0
BM_format_string<char>/262144 -0.0073 -0.0086 1 1 1 1
BM_format_string<char>/524288 +0.0017 +0.0005 1 1 1 1
BM_format_string<char>/1048576 +0.0039 +0.0037 1 1 1 1
BM_format_string<wchar_t>/1 -0.1304 -0.1307 56 49 56 49
BM_format_string<wchar_t>/2 -0.1285 -0.1286 28 24 28 24
BM_format_string<wchar_t>/4 -0.1288 -0.1288 14 12 14 12
BM_format_string<wchar_t>/8 -0.1547 -0.1547 9 8 9 8
BM_format_string<wchar_t>/16 -0.1681 -0.1681 5 4 5 4
BM_format_string<wchar_t>/32 -0.1579 -0.1580 2 2 2 2
BM_format_string<wchar_t>/64 -0.2443 -0.2444 1 1 1 1
BM_format_string<wchar_t>/128 -0.4400 -0.4399 1 1 1 1
BM_format_string<wchar_t>/256 -0.0535 -0.0535 1 1 1 1
BM_format_string<wchar_t>/512 -0.0563 -0.0563 1 1 1 1
BM_format_string<wchar_t>/1024 -0.1018 -0.1018 1 1 1 1
BM_format_string<wchar_t>/2048 -0.0910 -0.0910 1 0 1 0
BM_format_string<wchar_t>/4096 +0.4528 +0.4527 1 1 1 1
BM_format_string<wchar_t>/8192 +0.3121 +0.3124 1 1 1 1
BM_format_string<wchar_t>/16384 +0.2059 +0.2059 1 1 1 1
BM_format_string<wchar_t>/32768 +0.1316 +0.1290 1 1 1 1
BM_format_string<wchar_t>/65536 +0.1604 +0.1610 1 1 1 1
BM_format_string<wchar_t>/131072 +0.1326 +0.1326 1 1 1 1
BM_format_string<wchar_t>/262144 +0.1181 +0.1179 3 3 3 3
BM_format_string<wchar_t>/524288 +0.5515 +0.5527 2 3 2 3
BM_format_string<wchar_t>/1048576 +0.1007 +0.1011 2 3 2 3
OVERALL_GEOMEAN -0.1685 -0.1693 0 0 0 0


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

2 Files Affected:

  • (modified) libcxx/include/__format/buffer.h (+237-18)
  • (modified) libcxx/include/__format/format_functions.h (+12-12)
diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h
index 8598f0a1c0395..1f26bfa923a6a 100644
--- a/libcxx/include/__format/buffer.h
+++ b/libcxx/include/__format/buffer.h
@@ -58,23 +58,156 @@ namespace __format {
 /// This helper is used together with the @ref back_insert_iterator to offer
 /// type-erasure for the formatting functions. This reduces the number to
 /// template instantiations.
+///
+/// The design of the class is being changed to improve performance and do some
+/// code cleanups.
+/// The original design (as shipped up to LLVM-19) uses the following design:
+/// - There is an external object that connects the buffer to the output.
+/// - The class constructor stores a function pointer to a grow function and a
+///   type-erased pointer to the object that does the grow.
+/// - When writing data to the buffer would exceed the external buffer's
+///   capacity it requests the external buffer to flush its contents.
+///
+/// The new design tries to solve some issues with the current design:
+/// - The buffer used is a fixed-size buffer, benchmarking shows that using a
+///   dynamic allocated buffer has performance benefits.
+/// - Implementing P3107R5 "Permit an efficient implementation of std::print"
+///   is not trivial with the current buffers. Using the code from this series
+///   makes it trivial.
+///
+/// This class is ABI-tagged, still the new design does not change the size of
+/// objects of this class.
+///
+/// The new design contains information regarding format_to_n changes, these
+/// will be implemented in follow-up patch.
+///
+/// The new design is the following.
+/// - There is an external object that connects the buffer to the output.
+/// - This buffer object:
+///   - inherits publicly from this class.
+///   - has a static or dynamic buffer.
+///   - has a static member function to make space in its buffer write
+///     operations. This can be done by increasing the size of the internal
+///     buffer or by writing the contents of the buffer to the output iterator.
+///
+///     This member function is a constructor argument, so its name is not
+///     fixed. The code uses the name __prepare_write.
+/// - The number of output code units can be limited by a __max_output_size
+///   object. This is used in format_to_n This object:
+///   - Contains the maximum number of code units to be written.
+///   - Contains the number of code units that are requested to be written.
+///     This number is returned to the user of format_to_n.
+///   - The write functions call objects __request_write member function.
+///     This function:
+///     - Updates the number of code units that are requested to be written.
+///     - Returns the number of code units that can be written without
+///       exceeding the maximum number of code units to be written.
+///
+/// Documentation for the buffer usage members:
+/// - __ptr_ the start of the buffer.
+/// - __capacity_ the number of code units that can be written.
+///   This means [__ptr_, __ptr_ + __capacity_) is a valid range to write to.
+/// - __size_ the number of code units written in the buffer. The next code
+///   unit will be written at __ptr_ + __size_. This __size_ may NOT contain
+///   the total number of code units written by the __output_buffer. Whether or
+///   not it does depends on the sub-class used. Typically the total number of
+///   code units written is not interesting. It is interesting for format_to_n
+///   which has its own way to track this number.
+///
+/// Documentation for the buffer changes function:
+/// The subclasses have a function with the following signature:
+///
+///   static void __prepare_write(
+///     __output_buffer<_CharT>& __buffer, size_t __code_units);
+///
+/// This function is called when a write function writes more code units than
+/// the buffer' available space. When an __max_output_size object is provided
+/// the number of code units is the number of code units returned from
+/// __max_output_size::__request_write function.
+///
+/// - The __buffer contains *this. Since the class containing this function
+///   inherits from __output_buffer it's save to cast it to the subclass being
+///   used.
+/// - The __code_units is the number of code units the caller will write + 1.
+///   - This value does not take the avaiable space of the buffer into account.
+///   - The push_back function is more efficient when writing before resizing,
+///     this means the buffer should always have room for one code unit. Hence
+///     the + 1 is the size.
+/// - When the function returns there is room for at least one code unit. There
+///   is no requirement there is room for __code_units code units:
+///   - The class has some "bulk" operations. For example, __copy which copies
+///     the contents of a basic_string_view to the output. If the sub-class has
+///     a fixed size buffer the size of the basic_string_view may be larger
+///     than the buffer. In that case it's impossible to honor the requested
+///     size.
+///   - The at least one code unit makes sure the entire output can be written.
+///     (Obviously making room one code unit at a time is slow and
+///     it's recommended to return a larger available space.)
+///   - When the buffer has room for at least one code unit the function may be
+///     a no-op.
+/// - When the function makes space for more code units it uses one for these
+///   functions to signal the change:
+///   - __buffer_flushed()
+///     - This function is typically used for a fixed sized buffer.
+///     - The current contents of [__ptr_, __ptr_ + __size_) have been
+///       processed.
+///     - __ptr_ remains unchanged.
+///     - __capacity_ remains unchanged.
+///     - __size_ will be set to 0.
+///   - __buffer_moved(_CharT* __ptr, size_t __capacity)
+///     - This function is typically used for a dynamic sized buffer. There the
+///       location of the buffer changes due to reallocations.
+///     - __ptr_ will be set to __ptr. (This value may be the old value of
+///       __ptr_).
+///     - __capacity_ will be set to __capacity. (This value may be the old
+///       value of       __capacity_).
+///     - __size_ remains unchanged,
+///     - The range [__ptr, __ptr + __size_) contains the original data of the
+///       range  [__ptr_, __ptr_ + __size_).
+///
+/// The push_back function expects a valid buffer and a capacity of at least 1.
+/// This means:
+/// - The class is constructed with a valid buffer,
+/// - __buffer_moved is called with a valid buffer is used before the first
+///   write operation,
+/// - no write function is ever called, or
+/// - the class is constructed with a __max_output_size object with __max_size 0.
+///
+/// The latter option allows formatted_size to use the output buffer without
+/// ever writing anything to the buffer.
 template <__fmt_char_type _CharT>
 class _LIBCPP_TEMPLATE_VIS __output_buffer {
 public:
-  using value_type = _CharT;
+  using value_type           = _CharT;
+  using __prepare_write_type = void (*)(__output_buffer<_CharT>&, size_t);
 
-  template <class _Tp>
+  template <class _Tp> // Deprecated LLVM-19 function.
   _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, _Tp* __obj)
       : __ptr_(__ptr),
         __capacity_(__capacity),
         __flush_([](_CharT* __p, size_t __n, void* __o) { static_cast<_Tp*>(__o)->__flush(__p, __n); }),
         __obj_(__obj) {}
 
+  // New LLVM-20 function.
+  [[nodiscard]]
+  _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, __prepare_write_type __prepare_write)
+      : __ptr_(__ptr), __capacity_(__capacity), __prepare_write_(__prepare_write), __obj_(nullptr) {}
+
+  // Deprecated LLVM-19 function.
   _LIBCPP_HIDE_FROM_ABI void __reset(_CharT* __ptr, size_t __capacity) {
     __ptr_      = __ptr;
     __capacity_ = __capacity;
   }
 
+  // New LLVM-20 function.
+  _LIBCPP_HIDE_FROM_ABI void __buffer_flused() { __size_ = 0; }
+
+  // New LLVM-20 function.
+  _LIBCPP_HIDE_FROM_ABI void __buffer_moved(_CharT* __ptr, size_t __capacity) {
+    __ptr_      = __ptr;
+    __capacity_ = __capacity;
+  }
+
   _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return std::back_insert_iterator{*this}; }
 
   // Used in std::back_insert_iterator.
@@ -84,7 +217,7 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
     // Profiling showed flushing after adding is more efficient than flushing
     // when entering the function.
     if (__size_ == __capacity_)
-      __flush();
+      __flush(0);
   }
 
   /// Copies the input __str to the buffer.
@@ -107,7 +240,7 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
     size_t __n = __str.size();
 
     __flush_on_overflow(__n);
-    if (__n < __capacity_) { //  push_back requires the buffer to have room for at least one character (so use <).
+    if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <).
       std::copy_n(__str.data(), __n, std::addressof(__ptr_[__size_]));
       __size_ += __n;
       return;
@@ -118,12 +251,12 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
     _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow");
     const _InCharT* __first = __str.data();
     do {
-      size_t __chunk = std::min(__n, __capacity_);
+      size_t __chunk = std::min(__n, __capacity_ - __size_);
       std::copy_n(__first, __chunk, std::addressof(__ptr_[__size_]));
       __size_ = __chunk;
       __first += __chunk;
       __n -= __chunk;
-      __flush();
+      __flush(__n);
     } while (__n);
   }
 
@@ -148,12 +281,12 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
     // Transform the data in "__capacity_" sized chunks.
     _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow");
     do {
-      size_t __chunk = std::min(__n, __capacity_);
+      size_t __chunk = std::min(__n, __capacity_ - __size_);
       std::transform(__first, __first + __chunk, std::addressof(__ptr_[__size_]), __operation);
       __size_ = __chunk;
       __first += __chunk;
       __n -= __chunk;
-      __flush();
+      __flush(__n);
     } while (__n);
   }
 
@@ -174,20 +307,36 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
       std::fill_n(std::addressof(__ptr_[__size_]), __chunk, __value);
       __size_ = __chunk;
       __n -= __chunk;
-      __flush();
+      __flush(__n);
     } while (__n);
   }
 
-  _LIBCPP_HIDE_FROM_ABI void __flush() {
-    __flush_(__ptr_, __size_, __obj_);
-    __size_ = 0;
+  _LIBCPP_HIDE_FROM_ABI void __flush(size_t __size_hint) {
+    if (__obj_) {
+      // LLVM-19 code path
+      __flush_(__ptr_, __size_, __obj_);
+      __size_ = 0;
+    } else {
+      // LLVM-20 code path
+      __prepare_write_(*this, __size_hint + 1); // + 1 to always have space for the next time
+    }
   }
 
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __capacity() const { return __capacity_; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __size() const { return __size_; }
+
 private:
   _CharT* __ptr_;
   size_t __capacity_;
   size_t __size_{0};
-  void (*__flush_)(_CharT*, size_t, void*);
+  union {
+    // LLVM-19 member
+    void (*__flush_)(_CharT*, size_t, void*);
+    // LLVM-20 member
+    void (*__prepare_write_)(__output_buffer<_CharT>&, size_t);
+  };
+  static_assert(sizeof(__flush_) == sizeof(__prepare_write_), "The union is an ABI break.");
+  static_assert(alignof(decltype(__flush_)) == alignof(decltype(__prepare_write_)), "The union is an ABI break.");
   void* __obj_;
 
   /// Flushes the buffer when the output operation would overflow the buffer.
@@ -224,11 +373,14 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
   /// the buffers. This would make the code more complex and \ref format_to_n is
   /// not the most common use case. Therefore the optimization isn't done.
   _LIBCPP_HIDE_FROM_ABI void __flush_on_overflow(size_t __n) {
-    if (__size_ + __n >= __capacity_)
-      __flush();
+    __n += __size_;
+    if (__n >= __capacity_)
+      __flush(__n - __capacity_ + 1);
   }
 };
 
+// ***** ***** ***** LLVM-19 classes ***** ***** *****
+
 /// A storage using an internal buffer.
 ///
 /// This storage is used when writing a single element to the output iterator
@@ -373,7 +525,7 @@ class _LIBCPP_TEMPLATE_VIS __format_buffer {
   _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { __writer_.__flush(__ptr, __n); }
 
   _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && {
-    __output_.__flush();
+    __output_.__flush(0);
     return std::move(__writer_).__out_it();
   }
 
@@ -395,7 +547,7 @@ class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer {
   _LIBCPP_HIDE_FROM_ABI void __flush(const _CharT*, size_t __n) { __size_ += __n; }
 
   _LIBCPP_HIDE_FROM_ABI size_t __result() && {
-    __output_.__flush();
+    __output_.__flush(0);
     return __size_;
   }
 
@@ -499,11 +651,78 @@ struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final
   _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return this->__output_.__make_output_iterator(); }
 
   _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && {
-    this->__output_.__flush();
+    this->__output_.__flush(0);
     return {std::move(this->__writer_).__out_it(), this->__size_};
   }
 };
 
+// ***** ***** ***** LLVM-20 classes ***** ***** *****
+
+// A dynamically growing buffer.
+template <__fmt_char_type _CharT>
+class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT> {
+public:
+  __allocating_buffer(const __allocating_buffer&)            = delete;
+  __allocating_buffer& operator=(const __allocating_buffer&) = delete;
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __allocating_buffer()
+      : __output_buffer<_CharT>{__buffer_, __buffer_size_, __prepare_write} {}
+
+  _LIBCPP_HIDE_FROM_ABI ~__allocating_buffer() {
+    if (__ptr_ != __buffer_) {
+      ranges::destroy_n(__ptr_, this->__size());
+      allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, this->__capacity());
+    }
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, this->__size()}; }
+
+private:
+  // At the moment the allocator is hard-code. There might be reasons to have
+  // an allocator trait in the future. This ensures forward compatibility.
+  using _Alloc = allocator<_CharT>;
+  _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_;
+
+  // Since allocating is expensive the class has a small internal buffer. When
+  // its capacity is exceeded a dynamic buffer will be allocated.
+  static constexpr size_t __buffer_size_ = 256;
+  _CharT __buffer_[__buffer_size_];
+  _CharT* __ptr_{__buffer_};
+
+  _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) {
+    if (__capacity < __buffer_size_)
+      return;
+
+    _LIBCPP_ASSERT_INTERNAL(__capacity > this->__capacity(), "the buffer must grow");
+    auto __result = std::__allocate_at_least(__alloc_, __capacity);
+    auto __guard  = std::__make_exception_guard([&] {
+      allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count);
+    });
+    // This shouldn't throw, but just to be safe. Note that at -O1 this
+    // guard is optimized away so there is no runtime overhead.
+    new (__result.ptr) _CharT[__result.count];
+    std::copy_n(__ptr_, this->__size(), __result.ptr);
+    __guard.__complete();
+    if (__ptr_ != __buffer_) {
+      ranges::destroy_n(__ptr_, this->__capacity());
+      allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, this->__capacity());
+    }
+
+    __ptr_ = __result.ptr;
+    this->__buffer_moved(__ptr_, __result.count);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI void __prepare_write(size_t __size_hint) {
+    __grow_buffer(std::max<size_t>(this->__capacity() + __size_hint, this->__capacity() * 1.6));
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static void __prepare_write(__output_buffer<_CharT>& __buffer, size_t __size_hint) {
+    static_cast<__allocating_buffer<_CharT>&>(__buffer).__prepare_write(__size_hint);
+  }
+};
+
+// ***** ***** ***** LLVM-19 and LLVM-20 class ***** ***** *****
+
 // A dynamically growing buffer intended to be used for retargeting a context.
 //
 // P2286 Formatting ranges adds range formatting support. It allows the user to
diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h
index d14b49aff1495..a5c63bd4db70f 100644
--- a/libcxx/include/__format/format_functions.h
+++ b/libcxx/include/__format/format_functions.h
@@ -452,9 +452,9 @@ format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) {
 // fires too eagerly, see http://llvm.org/PR61563.
 template <class = void>
 [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) {
-  string __res;
-  std::vformat_to(std::back_inserter(__res), __fmt, __args);
-  return __res;
+  __format::__allocating_buffer<char> __buffer;
+  std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args);
+  return string{__buffer.__view()};
 }
 
 #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
@@ -463,9 +463,9 @@ template <class = void>
 template <class = void>
 [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
 vformat(wstring_view __fmt, wformat_args __args) {
-  wstring __res;
-  std::vformat_to(std::back_inserter(__res), __fmt, __args);
-  return __res;
+  __format::__allocating_buffer<wchar_t> __buffer;
+  std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args);
+  return wstring{__buffer.__view()};
 }
 #  endif
 
@@ -585,9 +585,9 @@ format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&
 template <class = void>
 [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string
 vformat(locale __loc, string_view __fmt, format_args __args) {
-  string __res;
-  std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args);
-  return __res;
+  __format::__allocating_buffer<char> __buffer;
+  std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args);
+  return string{__buffer.__view()};
 }
 
 #    ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
@@ -596,9 +596,9 @@ vformat(locale __loc, string_view __fmt, format_args __args) {
 template <class = void>
 [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
 vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
-  wstring __res;
-  std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args);
-  return __res;
+  __format::__allocating_buffer<wchar_t> __buffer;
+  std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args);
+  return wstring{__buffer.__view()};
 }
 #    endif
 

Comment on lines +64 to +70
/// The original design (as shipped up to LLVM-19) uses the following design:
/// - There is an external object that connects the buffer to the output.
/// - The class constructor stores a function pointer to a grow function and a
/// type-erased pointer to the object that does the grow.
/// - When writing data to the buffer would exceed the external buffer's
/// capacity it requests the external buffer to flush its contents.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the last patch in the series will remove this comment.
The implementation itself is in a transition state too, this also will be cleaned in the final patch of the series.

This changes the __output_buffer to a new structure. Since the other
formatting fucntions std::format_to, std::format_to_n, and
std::formatted_size still use the old codepaths the class is in a
transition state. At the end of the series the class should be in its
final state.

write_double_comparison:

Before
----------------------------------------------------------------------------------------
Benchmark                                              Time             CPU   Iterations
----------------------------------------------------------------------------------------
BM_sprintf                                           197 ns          196 ns      3550000
BM_to_string                                         218 ns          218 ns      3214000
BM_to_chars                                         42.4 ns         42.3 ns     16575000
BM_to_chars_as_string                               48.2 ns         48.1 ns     14542000
BM_format                                            175 ns          175 ns      4000000
BM_format_to_back_inserter<std::string>              175 ns          175 ns      3995000
BM_format_to_back_inserter<std::vector<char>>        207 ns          206 ns      3393000
BM_format_to_back_inserter<std::list<char>>          752 ns          750 ns       931000
BM_format_to_iterator/<std::array>                   161 ns          161 ns      4345000
BM_format_to_iterator/<std::string>                  161 ns          161 ns      4344000
BM_format_to_iterator/<std::vector>                  162 ns          161 ns      4344000

After
----------------------------------------------------------------------------------------
Benchmark                                              Time             CPU   Iterations
----------------------------------------------------------------------------------------
BM_sprintf                                           197 ns          197 ns      3550000
BM_to_string                                         219 ns          219 ns      3199000
BM_to_chars                                         42.4 ns         42.4 ns     16554000
BM_to_chars_as_string                               48.1 ns         48.1 ns     14569000
BM_format                                            167 ns          167 ns      4203000
BM_format_to_back_inserter<std::string>              179 ns          179 ns      3920000
BM_format_to_back_inserter<std::vector<char>>        214 ns          214 ns      3274000
BM_format_to_back_inserter<std::list<char>>          751 ns          751 ns       930000
BM_format_to_iterator/<std::array>                   164 ns          164 ns      4258000
BM_format_to_iterator/<std::string>                  165 ns          164 ns      4247000
BM_format_to_iterator/<std::vector>                  165 ns          165 ns      4248000

Comparison
Benchmark                                                       Time             CPU      Time Old      Time New       CPU Old       CPU New
--------------------------------------------------------------------------------------------------------------------------------------------
BM_sprintf                                                   +0.0013         +0.0028           197           197           196           197
BM_to_string                                                 +0.0023         +0.0038           218           219           218           219
BM_to_chars                                                  +0.0014         +0.0030            42            42            42            42
BM_to_chars_as_string                                        -0.0025         -0.0010            48            48            48            48
BM_format                                                    -0.0476         -0.0462           175           167           175           167
BM_format_to_back_inserter<std::string>                      +0.0190         +0.0205           175           179           175           179
BM_format_to_back_inserter<std::vector<char>>                +0.0348         +0.0363           207           214           206           214
BM_format_to_back_inserter<std::list<char>>                  -0.0013         +0.0005           752           751           750           751
BM_format_to_iterator/<std::array>                           +0.0188         +0.0203           161           164           161           164
BM_format_to_iterator/<std::string>                          +0.0207         +0.0226           161           165           161           164
BM_format_to_iterator/<std::vector>                          +0.0197         +0.0212           162           165           161           165
OVERALL_GEOMEAN                                              +0.0058         +0.0074             0             0             0             0

write_int_comparison:

Before
----------------------------------------------------------------------------------------
Benchmark                                              Time             CPU   Iterations
----------------------------------------------------------------------------------------
BM_sprintf                                          79.6 ns         79.5 ns      8739000
BM_to_string                                        14.9 ns         14.9 ns     46713000
BM_to_chars                                         5.68 ns         5.67 ns    120614000
BM_to_chars_as_string                               14.2 ns         14.1 ns     49513000
BM_format                                           69.3 ns         69.2 ns     10105000
BM_format_to_back_inserter<std::string>             69.2 ns         69.1 ns     10138000
BM_format_to_back_inserter<std::vector<char>>       90.6 ns         90.5 ns      7728000
BM_format_to_back_inserter<std::list<char>>          234 ns          234 ns      2986000
BM_format_to_iterator/<std::array>                  59.3 ns         59.3 ns     11805000
BM_format_to_iterator/<std::string>                 58.7 ns         58.6 ns     11943000
BM_format_to_iterator/<std::vector>                 60.1 ns         60.1 ns     11670000

After
----------------------------------------------------------------------------------------
Benchmark                                              Time             CPU   Iterations
----------------------------------------------------------------------------------------
BM_sprintf                                          80.2 ns         80.2 ns      8670000
BM_to_string                                        15.0 ns         15.0 ns     46559000
BM_to_chars                                         4.93 ns         4.93 ns    138016000
BM_to_chars_as_string                               15.4 ns         15.4 ns     45415000
BM_format                                           62.1 ns         62.0 ns     11316000
BM_format_to_back_inserter<std::string>             70.2 ns         70.2 ns      9962000
BM_format_to_back_inserter<std::vector<char>>       92.8 ns         92.8 ns      7544000
BM_format_to_back_inserter<std::list<char>>          240 ns          240 ns      2917000
BM_format_to_iterator/<std::array>                  60.5 ns         60.5 ns     11572000
BM_format_to_iterator/<std::string>                 60.2 ns         60.2 ns     11653000
BM_format_to_iterator/<std::vector>                 60.1 ns         60.1 ns     11659000

Comparison
Benchmark                                                       Time             CPU      Time Old      Time New       CPU Old       CPU New
--------------------------------------------------------------------------------------------------------------------------------------------
BM_sprintf                                                   +0.0072         +0.0081            80            80            80            80
BM_to_string                                                 +0.0043         +0.0053            15            15            15            15
BM_to_chars                                                  -0.1324         -0.1316             6             5             6             5
BM_to_chars_as_string                                        +0.0895         +0.0906            14            15            14            15
BM_format                                                    -0.1047         -0.1040            69            62            69            62
BM_format_to_back_inserter<std::string>                      +0.0148         +0.0157            69            70            69            70
BM_format_to_back_inserter<std::vector<char>>                +0.0241         +0.0251            91            93            90            93
BM_format_to_back_inserter<std::list<char>>                  +0.0222         +0.0232           234           240           234           240
BM_format_to_iterator/<std::array>                           +0.0196         +0.0205            59            60            59            60
BM_format_to_iterator/<std::string>                          +0.0266         +0.0275            59            60            59            60
BM_format_to_iterator/<std::vector>                          -0.0004         +0.0005            60            60            60            60
OVERALL_GEOMEAN                                              -0.0045         -0.0036             0             0             0             0

write_string_comparison:

Before
---------------------------------------------------------------------------------------------------------------
Benchmark                                                                     Time             CPU   Iterations
---------------------------------------------------------------------------------------------------------------
BM_sprintf/C string len = 6                                                4.82 ns         4.82 ns    145548481
BM_format/C string len = 6                                                 55.1 ns         55.1 ns     12713693
BM_format_to_back_inserter<std::string>/C string len = 6                   55.1 ns         55.1 ns     12690821
BM_format_to_back_inserter<std::vector<char>>/C string len = 6             71.5 ns         71.5 ns      9805550
BM_format_to_back_inserter<std::deque<char>>/C string len = 6               154 ns          154 ns      4536256
BM_format_to_back_inserter<std::list<char>>/C string len = 6                130 ns          130 ns      5348845
BM_format_to_iterator/<std::array> C string len = 6                        44.9 ns         44.9 ns     15556175
BM_format_to_iterator/<std::string> C string len = 6                       45.8 ns         45.8 ns     15290662
BM_format_to_iterator/<std::vector> C string len = 6                       44.4 ns         44.4 ns     15807704
BM_format_to_iterator/<std::deque> C string len = 6                        50.0 ns         50.0 ns     13973893
BM_format/string len = 6                                                   54.7 ns         54.7 ns     12793406
BM_format_to_back_inserter<std::string>/string len = 6                     55.5 ns         55.5 ns     12620370
BM_format_to_back_inserter<std::vector<char>>/string len = 6               70.4 ns         70.4 ns      9936490
BM_format_to_back_inserter<std::deque<char>>/string len = 6                 155 ns          155 ns      4521357
BM_format_to_back_inserter<std::list<char>>/string len = 6                  135 ns          135 ns      5201519
BM_format_to_iterator/<std::array> string len = 6                          44.6 ns         44.6 ns     15703872
BM_format_to_iterator/<std::string> string len = 6                         45.0 ns         45.0 ns     15545182
BM_format_to_iterator/<std::vector> string len = 6                         45.0 ns         45.0 ns     15539130
BM_format_to_iterator/<std::deque> string len = 6                          50.5 ns         50.5 ns     13846916
BM_format/string_view len = 6                                              54.6 ns         54.6 ns     12821301
BM_format_to_back_inserter<std::string>/string_view len = 6                54.6 ns         54.6 ns     12827673
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6          69.9 ns         69.9 ns      9958365
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6            157 ns          157 ns      4462445
BM_format_to_back_inserter<std::list<char>>/string_view len = 6             134 ns          134 ns      5232155
BM_format_to_iterator/<std::array> string_view len = 6                     44.2 ns         44.2 ns     15871362
BM_format_to_iterator/<std::string> string_view len = 6                    45.0 ns         45.0 ns     15582582
BM_format_to_iterator/<std::vector> string_view len = 6                    45.1 ns         45.1 ns     15539906
BM_format_to_iterator/<std::deque> string_view len = 6                     50.5 ns         50.5 ns     13896524
BM_sprintf/C string len = 60                                               4.15 ns         4.15 ns    168165776
BM_format/C string len = 60                                                73.8 ns         73.8 ns      9498291
BM_format_to_back_inserter<std::string>/C string len = 60                  73.6 ns         73.6 ns      9535890
BM_format_to_back_inserter<std::vector<char>>/C string len = 60            83.1 ns         83.1 ns      8428154
BM_format_to_back_inserter<std::deque<char>>/C string len = 60              281 ns          281 ns      2490093
BM_format_to_back_inserter<std::list<char>>/C string len = 60              1157 ns         1157 ns       605227
BM_format_to_iterator/<std::array> C string len = 60                       44.9 ns         44.9 ns     15604442
BM_format_to_iterator/<std::string> C string len = 60                      45.8 ns         45.8 ns     15272196
BM_format_to_iterator/<std::vector> C string len = 60                      44.6 ns         44.7 ns     15683193
BM_format_to_iterator/<std::deque> C string len = 60                       50.6 ns         50.6 ns     13698382
BM_format/string len = 60                                                  72.3 ns         72.3 ns      9648955
BM_format_to_back_inserter<std::string>/string len = 60                    72.0 ns         72.0 ns      9738373
BM_format_to_back_inserter<std::vector<char>>/string len = 60              82.3 ns         82.3 ns      8517896
BM_format_to_back_inserter<std::deque<char>>/string len = 60                280 ns          280 ns      2496054
BM_format_to_back_inserter<std::list<char>>/string len = 60                1162 ns         1162 ns       602383
BM_format_to_iterator/<std::array> string len = 60                         44.5 ns         44.5 ns     15727799
BM_format_to_iterator/<std::string> string len = 60                        49.6 ns         49.6 ns     14096012
BM_format_to_iterator/<std::vector> string len = 60                        49.8 ns         49.8 ns     14053734
BM_format_to_iterator/<std::deque> string len = 60                         50.8 ns         50.8 ns     13801448
BM_format/string_view len = 60                                             72.5 ns         72.5 ns      9653638
BM_format_to_back_inserter<std::string>/string_view len = 60               72.7 ns         72.7 ns      9598203
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60         81.9 ns         81.9 ns      8522306
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60           283 ns          283 ns      2475014
BM_format_to_back_inserter<std::list<char>>/string_view len = 60           1162 ns         1162 ns       600924
BM_format_to_iterator/<std::array> string_view len = 60                    44.1 ns         44.1 ns     15858951
BM_format_to_iterator/<std::string> string_view len = 60                   44.9 ns         44.9 ns     15579340
BM_format_to_iterator/<std::vector> string_view len = 60                   44.9 ns         44.9 ns     15586711
BM_format_to_iterator/<std::deque> string_view len = 60                    50.0 ns         50.0 ns     13980804
BM_sprintf/C string len = 6000                                              116 ns          116 ns      6051541
BM_format/C string len = 6000                                              1000 ns         1000 ns       698647
BM_format_to_back_inserter<std::string>/C string len = 6000                1002 ns         1002 ns       701440
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000           956 ns          956 ns       727585
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000          14898 ns        14898 ns        46994
BM_format_to_back_inserter<std::list<char>>/C string len = 6000          114860 ns       114859 ns         6106
BM_format_to_iterator/<std::array> C string len = 6000                      158 ns          158 ns      4425133
BM_format_to_iterator/<std::string> C string len = 6000                     161 ns          161 ns      4335471
BM_format_to_iterator/<std::vector> C string len = 6000                     157 ns          157 ns      4444174
BM_format_to_iterator/<std::deque> C string len = 6000                      445 ns          445 ns      1574120
BM_format/string len = 6000                                                 929 ns          929 ns       753630
BM_format_to_back_inserter<std::string>/string len = 6000                   930 ns          930 ns       752888
BM_format_to_back_inserter<std::vector<char>>/string len = 6000             910 ns          910 ns       771111
BM_format_to_back_inserter<std::deque<char>>/string len = 6000            14875 ns        14876 ns        47221
BM_format_to_back_inserter<std::list<char>>/string len = 6000            114937 ns       114936 ns         6092
BM_format_to_iterator/<std::array> string len = 6000                        118 ns          118 ns      5963643
BM_format_to_iterator/<std::string> string len = 6000                       106 ns          106 ns      6584711
BM_format_to_iterator/<std::vector> string len = 6000                       106 ns          106 ns      6583118
BM_format_to_iterator/<std::deque> string len = 6000                        391 ns          391 ns      1790538
BM_format/string_view len = 6000                                            935 ns          935 ns       744348
BM_format_to_back_inserter<std::string>/string_view len = 6000              934 ns          934 ns       742039
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000        895 ns          895 ns       783527
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000       14864 ns        14865 ns        47122
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000       115042 ns       115044 ns         6091
BM_format_to_iterator/<std::array> string_view len = 6000                   115 ns          115 ns      6070197
BM_format_to_iterator/<std::string> string_view len = 6000                  116 ns          116 ns      6035109
BM_format_to_iterator/<std::vector> string_view len = 6000                  115 ns          115 ns      6067683
BM_format_to_iterator/<std::deque> string_view len = 6000                   387 ns          387 ns      1803466

After
---------------------------------------------------------------------------------------------------------------
Benchmark                                                                     Time             CPU   Iterations
---------------------------------------------------------------------------------------------------------------
BM_sprintf/C string len = 6                                                3.56 ns         3.56 ns    196337806
BM_format/C string len = 6                                                 49.1 ns         49.1 ns     14241174
BM_format_to_back_inserter<std::string>/C string len = 6                   56.8 ns         56.8 ns     12341483
BM_format_to_back_inserter<std::vector<char>>/C string len = 6             72.9 ns         72.9 ns      9610864
BM_format_to_back_inserter<std::deque<char>>/C string len = 6               155 ns          155 ns      4528719
BM_format_to_back_inserter<std::list<char>>/C string len = 6                137 ns          137 ns      5103340
BM_format_to_iterator/<std::array> C string len = 6                        46.4 ns         46.4 ns     15081626
BM_format_to_iterator/<std::string> C string len = 6                       47.0 ns         47.0 ns     14893458
BM_format_to_iterator/<std::vector> C string len = 6                       45.9 ns         45.9 ns     15243762
BM_format_to_iterator/<std::deque> C string len = 6                        52.6 ns         52.6 ns     13323560
BM_format/string len = 6                                                   49.3 ns         49.3 ns     14181485
BM_format_to_back_inserter<std::string>/string len = 6                     55.4 ns         55.4 ns     12644078
BM_format_to_back_inserter<std::vector<char>>/string len = 6               72.7 ns         72.7 ns      9618696
BM_format_to_back_inserter<std::deque<char>>/string len = 6                 154 ns          154 ns      4540873
BM_format_to_back_inserter<std::list<char>>/string len = 6                  134 ns          134 ns      5220153
BM_format_to_iterator/<std::array> string len = 6                          46.5 ns         46.5 ns     15064445
BM_format_to_iterator/<std::string> string len = 6                         47.3 ns         47.3 ns     14786851
BM_format_to_iterator/<std::vector> string len = 6                         46.5 ns         46.5 ns     15069381
BM_format_to_iterator/<std::deque> string len = 6                          52.9 ns         52.9 ns     13207437
BM_format/string_view len = 6                                              47.6 ns         47.6 ns     14688449
BM_format_to_back_inserter<std::string>/string_view len = 6                56.1 ns         56.1 ns     12514239
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6          72.0 ns         72.0 ns      9705591
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6            152 ns          152 ns      4607470
BM_format_to_back_inserter<std::list<char>>/string_view len = 6             134 ns          134 ns      5233005
BM_format_to_iterator/<std::array> string_view len = 6                     46.0 ns         46.0 ns     15205542
BM_format_to_iterator/<std::string> string_view len = 6                    46.5 ns         46.5 ns     15067775
BM_format_to_iterator/<std::vector> string_view len = 6                    46.5 ns         46.5 ns     15057288
BM_format_to_iterator/<std::deque> string_view len = 6                     51.8 ns         51.8 ns     13564649
BM_sprintf/C string len = 60                                               4.83 ns         4.83 ns    145020116
BM_format/C string len = 60                                                72.3 ns         72.3 ns      9665555
BM_format_to_back_inserter<std::string>/C string len = 60                  85.0 ns         85.0 ns      8249050
BM_format_to_back_inserter<std::vector<char>>/C string len = 60            94.7 ns         94.7 ns      7398143
BM_format_to_back_inserter<std::deque<char>>/C string len = 60              286 ns          286 ns      2452225
BM_format_to_back_inserter<std::list<char>>/C string len = 60              1179 ns         1179 ns       595011
BM_format_to_iterator/<std::array> C string len = 60                       46.1 ns         46.1 ns     15157525
BM_format_to_iterator/<std::string> C string len = 60                      47.0 ns         47.0 ns     14899863
BM_format_to_iterator/<std::vector> C string len = 60                      45.8 ns         45.8 ns     15272542
BM_format_to_iterator/<std::deque> C string len = 60                       58.7 ns         58.7 ns     11958910
BM_format/string len = 60                                                  61.7 ns         61.7 ns     11308865
BM_format_to_back_inserter<std::string>/string len = 60                    74.2 ns         74.2 ns      9401855
BM_format_to_back_inserter<std::vector<char>>/string len = 60              86.6 ns         86.6 ns      8079197
BM_format_to_back_inserter<std::deque<char>>/string len = 60                278 ns          278 ns      2519254
BM_format_to_back_inserter<std::list<char>>/string len = 60                1169 ns         1170 ns       597703
BM_format_to_iterator/<std::array> string len = 60                         46.4 ns         46.4 ns     15074759
BM_format_to_iterator/<std::string> string len = 60                        47.3 ns         47.3 ns     14801107
BM_format_to_iterator/<std::vector> string len = 60                        46.3 ns         46.4 ns     15085548
BM_format_to_iterator/<std::deque> string len = 60                         52.2 ns         52.2 ns     13331015
BM_format/string_view len = 60                                             65.0 ns         65.0 ns     10756847
BM_format_to_back_inserter<std::string>/string_view len = 60               78.5 ns         78.5 ns      9051370
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60         87.9 ns         87.9 ns      7946825
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60           280 ns          280 ns      2505999
BM_format_to_back_inserter<std::list<char>>/string_view len = 60           1174 ns         1174 ns       594829
BM_format_to_iterator/<std::array> string_view len = 60                    46.3 ns         46.3 ns     15149785
BM_format_to_iterator/<std::string> string_view len = 60                   46.7 ns         46.7 ns     15002678
BM_format_to_iterator/<std::vector> string_view len = 60                   46.7 ns         46.7 ns     14996445
BM_format_to_iterator/<std::deque> string_view len = 60                    52.6 ns         52.6 ns     13255470
BM_sprintf/C string len = 6000                                             77.1 ns         77.1 ns      9099121
BM_format/C string len = 6000                                               350 ns          350 ns      2013049
BM_format_to_back_inserter<std::string>/C string len = 6000                 992 ns          992 ns       709093
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000          1016 ns         1016 ns       694784
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000          15158 ns        15159 ns        46125
BM_format_to_back_inserter<std::list<char>>/C string len = 6000          115703 ns       115705 ns         6055
BM_format_to_iterator/<std::array> C string len = 6000                      166 ns          166 ns      4224749
BM_format_to_iterator/<std::string> C string len = 6000                     153 ns          153 ns      4573034
BM_format_to_iterator/<std::vector> C string len = 6000                     150 ns          150 ns      4678898
BM_format_to_iterator/<std::deque> C string len = 6000                      465 ns          465 ns      1506323
BM_format/string len = 6000                                                 281 ns          281 ns      2462572
BM_format_to_back_inserter<std::string>/string len = 6000                   935 ns          935 ns       745376
BM_format_to_back_inserter<std::vector<char>>/string len = 6000             939 ns          939 ns       747498
BM_format_to_back_inserter<std::deque<char>>/string len = 6000            15069 ns        15069 ns        46429
BM_format_to_back_inserter<std::list<char>>/string len = 6000            115537 ns       115539 ns         6063
BM_format_to_iterator/<std::array> string len = 6000                        120 ns          120 ns      5849159
BM_format_to_iterator/<std::string> string len = 6000                       108 ns          108 ns      6482306
BM_format_to_iterator/<std::vector> string len = 6000                       107 ns          107 ns      6547915
BM_format_to_iterator/<std::deque> string len = 6000                        397 ns          397 ns      1763729
BM_format/string_view len = 6000                                            282 ns          282 ns      2490133
BM_format_to_back_inserter<std::string>/string_view len = 6000              927 ns          927 ns       750931
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000        946 ns          946 ns       735544
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000       15028 ns        15029 ns        46612
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000       115153 ns       115153 ns         6057
BM_format_to_iterator/<std::array> string_view len = 6000                   122 ns          122 ns      5753940
BM_format_to_iterator/<std::string> string_view len = 6000                  108 ns          108 ns      6507555
BM_format_to_iterator/<std::vector> string_view len = 6000                  107 ns          107 ns      6510450
BM_format_to_iterator/<std::deque> string_view len = 6000                   398 ns          398 ns      1762517

Comparison
Benchmark                                                                              Time             CPU      Time Old      Time New       CPU Old       CPU New
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
BM_sprintf/C string len = 6                                                         -0.2599         -0.2599             5             4             5             4
BM_format/C string len = 6                                                          -0.1094         -0.1095            55            49            55            49
BM_format_to_back_inserter<std::string>/C string len = 6                            +0.0316         +0.0316            55            57            55            57
BM_format_to_back_inserter<std::vector<char>>/C string len = 6                      +0.0204         +0.0204            71            73            71            73
BM_format_to_back_inserter<std::deque<char>>/C string len = 6                       +0.0023         +0.0023           154           155           154           155
BM_format_to_back_inserter<std::list<char>>/C string len = 6                        +0.0521         +0.0520           130           137           130           137
BM_format_to_iterator/<std::array> C string len = 6                                 +0.0317         +0.0317            45            46            45            46
BM_format_to_iterator/<std::string> C string len = 6                                +0.0265         +0.0265            46            47            46            47
BM_format_to_iterator/<std::vector> C string len = 6                                +0.0345         +0.0345            44            46            44            46
BM_format_to_iterator/<std::deque> C string len = 6                                 +0.0511         +0.0511            50            53            50            53
BM_format/string len = 6                                                            -0.0981         -0.0981            55            49            55            49
BM_format_to_back_inserter<std::string>/string len = 6                              -0.0028         -0.0028            56            55            56            55
BM_format_to_back_inserter<std::vector<char>>/string len = 6                        +0.0331         +0.0331            70            73            70            73
BM_format_to_back_inserter<std::deque<char>>/string len = 6                         -0.0040         -0.0040           155           154           155           154
BM_format_to_back_inserter<std::list<char>>/string len = 6                          -0.0019         -0.0019           135           134           135           134
BM_format_to_iterator/<std::array> string len = 6                                   +0.0427         +0.0427            45            46            45            46
BM_format_to_iterator/<std::string> string len = 6                                  +0.0515         +0.0515            45            47            45            47
BM_format_to_iterator/<std::vector> string len = 6                                  +0.0316         +0.0316            45            46            45            46
BM_format_to_iterator/<std::deque> string len = 6                                   +0.0475         +0.0475            51            53            51            53
BM_format/string_view len = 6                                                       -0.1267         -0.1267            55            48            55            48
BM_format_to_back_inserter<std::string>/string_view len = 6                         +0.0283         +0.0283            55            56            55            56
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6                   +0.0291         +0.0291            70            72            70            72
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6                    -0.0305         -0.0306           157           152           157           152
BM_format_to_back_inserter<std::list<char>>/string_view len = 6                     -0.0012         -0.0012           134           134           134           134
BM_format_to_iterator/<std::array> string_view len = 6                              +0.0426         +0.0426            44            46            44            46
BM_format_to_iterator/<std::string> string_view len = 6                             +0.0322         +0.0322            45            46            45            46
BM_format_to_iterator/<std::vector> string_view len = 6                             +0.0309         +0.0309            45            46            45            46
BM_format_to_iterator/<std::deque> string_view len = 6                              +0.0248         +0.0248            51            52            51            52
BM_sprintf/C string len = 60                                                        +0.1633         +0.1633             4             5             4             5
BM_format/C string len = 60                                                         -0.0203         -0.0203            74            72            74            72
BM_format_to_back_inserter<std::string>/C string len = 60                           +0.1548         +0.1548            74            85            74            85
BM_format_to_back_inserter<std::vector<char>>/C string len = 60                     +0.1395         +0.1395            83            95            83            95
BM_format_to_back_inserter<std::deque<char>>/C string len = 60                      +0.0157         +0.0157           281           286           281           286
BM_format_to_back_inserter<std::list<char>>/C string len = 60                       +0.0191         +0.0191          1157          1179          1157          1179
BM_format_to_iterator/<std::array> C string len = 60                                +0.0283         +0.0283            45            46            45            46
BM_format_to_iterator/<std::string> C string len = 60                               +0.0251         +0.0252            46            47            46            47
BM_format_to_iterator/<std::vector> C string len = 60                               +0.0263         +0.0263            45            46            45            46
BM_format_to_iterator/<std::deque> C string len = 60                                +0.1592         +0.1591            51            59            51            59
BM_format/string len = 60                                                           -0.1466         -0.1466            72            62            72            62
BM_format_to_back_inserter<std::string>/string len = 60                             +0.0299         +0.0299            72            74            72            74
BM_format_to_back_inserter<std::vector<char>>/string len = 60                       +0.0522         +0.0522            82            87            82            87
BM_format_to_back_inserter<std::deque<char>>/string len = 60                        -0.0099         -0.0099           280           278           280           278
BM_format_to_back_inserter<std::list<char>>/string len = 60                         +0.0062         +0.0062          1162          1169          1162          1170
BM_format_to_iterator/<std::array> string len = 60                                  +0.0430         +0.0430            45            46            45            46
BM_format_to_iterator/<std::string> string len = 60                                 -0.0466         -0.0466            50            47            50            47
BM_format_to_iterator/<std::vector> string len = 60                                 -0.0693         -0.0693            50            46            50            46
BM_format_to_iterator/<std::deque> string len = 60                                  +0.0275         +0.0275            51            52            51            52
BM_format/string_view len = 60                                                      -0.1034         -0.1034            73            65            73            65
BM_format_to_back_inserter<std::string>/string_view len = 60                        +0.0790         +0.0790            73            78            73            78
BM_format_to_back_inserter<std::vector<char>>/string_view len = 60                  +0.0735         +0.0735            82            88            82            88
BM_format_to_back_inserter<std::deque<char>>/string_view len = 60                   -0.0103         -0.0104           283           280           283           280
BM_format_to_back_inserter<std::list<char>>/string_view len = 60                    +0.0101         +0.0101          1162          1174          1162          1174
BM_format_to_iterator/<std::array> string_view len = 60                             +0.0484         +0.0484            44            46            44            46
BM_format_to_iterator/<std::string> string_view len = 60                            +0.0387         +0.0387            45            47            45            47
BM_format_to_iterator/<std::vector> string_view len = 60                            +0.0402         +0.0402            45            47            45            47
BM_format_to_iterator/<std::deque> string_view len = 60                             +0.0508         +0.0508            50            53            50            53
BM_sprintf/C string len = 6000                                                      -0.3337         -0.3337           116            77           116            77
BM_format/C string len = 6000                                                       -0.6500         -0.6500          1000           350          1000           350
BM_format_to_back_inserter<std::string>/C string len = 6000                         -0.0104         -0.0105          1002           992          1002           992
BM_format_to_back_inserter<std::vector<char>>/C string len = 6000                   +0.0630         +0.0630           956          1016           956          1016
BM_format_to_back_inserter<std::deque<char>>/C string len = 6000                    +0.0175         +0.0175         14898         15158         14898         15159
BM_format_to_back_inserter<std::list<char>>/C string len = 6000                     +0.0073         +0.0074        114860        115703        114859        115705
BM_format_to_iterator/<std::array> C string len = 6000                              +0.0504         +0.0504           158           166           158           166
BM_format_to_iterator/<std::string> C string len = 6000                             -0.0486         -0.0486           161           153           161           153
BM_format_to_iterator/<std::vector> C string len = 6000                             -0.0483         -0.0483           157           150           157           150
BM_format_to_iterator/<std::deque> C string len = 6000                              +0.0459         +0.0459           445           465           445           465
BM_format/string len = 6000                                                         -0.6975         -0.6975           929           281           929           281
BM_format_to_back_inserter<std::string>/string len = 6000                           +0.0050         +0.0050           930           935           930           935
BM_format_to_back_inserter<std::vector<char>>/string len = 6000                     +0.0321         +0.0322           910           939           910           939
BM_format_to_back_inserter<std::deque<char>>/string len = 6000                      +0.0130         +0.0130         14875         15069         14876         15069
BM_format_to_back_inserter<std::list<char>>/string len = 6000                       +0.0052         +0.0052        114937        115537        114936        115539
BM_format_to_iterator/<std::array> string len = 6000                                +0.0211         +0.0211           118           120           118           120
BM_format_to_iterator/<std::string> string len = 6000                               +0.0146         +0.0146           106           108           106           108
BM_format_to_iterator/<std::vector> string len = 6000                               +0.0048         +0.0048           106           107           106           107
BM_format_to_iterator/<std::deque> string len = 6000                                +0.0150         +0.0150           391           397           391           397
BM_format/string_view len = 6000                                                    -0.6989         -0.6989           935           282           935           282
BM_format_to_back_inserter<std::string>/string_view len = 6000                      -0.0083         -0.0083           934           927           934           927
BM_format_to_back_inserter<std::vector<char>>/string_view len = 6000                +0.0566         +0.0566           895           946           895           946
BM_format_to_back_inserter<std::deque<char>>/string_view len = 6000                 +0.0111         +0.0110         14864         15028         14865         15029
BM_format_to_back_inserter<std::list<char>>/string_view len = 6000                  +0.0010         +0.0009        115042        115153        115044        115153
BM_format_to_iterator/<std::array> string_view len = 6000                           +0.0560         +0.0560           115           122           115           122
BM_format_to_iterator/<std::string> string_view len = 6000                          -0.0693         -0.0693           116           108           116           108
BM_format_to_iterator/<std::vector> string_view len = 6000                          -0.0703         -0.0703           115           107           115           107
BM_format_to_iterator/<std::deque> string_view len = 6000                           +0.0271         +0.0271           387           398           387           398
OVERALL_GEOMEAN                                                                     -0.0350         -0.0350             0             0             0             0

format:
Before
--------------------------------------------------------------------------------------------
Benchmark                                  Time             CPU   Iterations UserCounters...
--------------------------------------------------------------------------------------------
BM_format_string<char>/1                55.5 ns         55.5 ns     12463288 bytes_per_second=17.187Mi/s
BM_format_string<char>/2                27.6 ns         27.6 ns     25421994 bytes_per_second=69.1874Mi/s
BM_format_string<char>/4                14.0 ns         14.0 ns     49785656 bytes_per_second=271.524Mi/s
BM_format_string<char>/8                7.07 ns         7.07 ns     99247048 bytes_per_second=1.05444Gi/s
BM_format_string<char>/16               3.53 ns         3.53 ns    198072224 bytes_per_second=4.21726Gi/s
BM_format_string<char>/32               2.31 ns         2.31 ns    302771136 bytes_per_second=12.9138Gi/s
BM_format_string<char>/64               1.15 ns         1.15 ns    606646976 bytes_per_second=51.7527Gi/s
BM_format_string<char>/128             0.597 ns        0.597 ns   1172263936 bytes_per_second=199.688Gi/s
BM_format_string<char>/256             0.327 ns        0.327 ns   2148927744 bytes_per_second=728.678Gi/s
BM_format_string<char>/512             0.248 ns        0.248 ns   2821635584 bytes_per_second=1.8779Ti/s
BM_format_string<char>/1024            0.203 ns        0.203 ns   3433579520 bytes_per_second=4.57798Ti/s
BM_format_string<char>/2048            0.164 ns        0.164 ns   4277524480 bytes_per_second=11.3793Ti/s
BM_format_string<char>/4096            0.137 ns        0.137 ns   5122269184 bytes_per_second=27.2589Ti/s
BM_format_string<char>/8192            0.126 ns        0.126 ns   5564243968 bytes_per_second=59.2812Ti/s
BM_format_string<char>/16384           0.136 ns        0.136 ns   5153013760 bytes_per_second=109.492Ti/s
BM_format_string<char>/32768           0.135 ns        0.135 ns   5165088768 bytes_per_second=219.985Ti/s
BM_format_string<char>/65536           0.243 ns        0.242 ns   2930180096 bytes_per_second=246.57Ti/s
BM_format_string<char>/131072          0.490 ns        0.489 ns   1437990912 bytes_per_second=243.75Ti/s
BM_format_string<char>/262144          0.593 ns        0.592 ns   1183055872 bytes_per_second=402.931Ti/s
BM_format_string<char>/524288          0.643 ns        0.641 ns   1092616192 bytes_per_second=743.445Ti/s
BM_format_string<char>/1048576         0.669 ns        0.668 ns   1045430272 bytes_per_second=1.39478Pi/s
BM_format_string<wchar_t>/1             56.0 ns         55.9 ns     12511543 bytes_per_second=68.2628Mi/s
BM_format_string<wchar_t>/2             28.0 ns         27.9 ns     25062366 bytes_per_second=273.519Mi/s
BM_format_string<wchar_t>/4             14.0 ns         14.0 ns     50257068 bytes_per_second=1.06742Gi/s
BM_format_string<wchar_t>/8             9.24 ns         9.21 ns     76118616 bytes_per_second=3.23473Gi/s
BM_format_string<wchar_t>/16            4.66 ns         4.65 ns    151420352 bytes_per_second=12.8261Gi/s
BM_format_string<wchar_t>/32            2.35 ns         2.35 ns    298417600 bytes_per_second=50.7972Gi/s
BM_format_string<wchar_t>/64            1.35 ns         1.34 ns    521608704 bytes_per_second=177.502Gi/s
BM_format_string<wchar_t>/128           1.03 ns         1.03 ns    680946304 bytes_per_second=463.91Gi/s
BM_format_string<wchar_t>/256          0.849 ns        0.847 ns    825871104 bytes_per_second=1.09901Ti/s
BM_format_string<wchar_t>/512          0.681 ns        0.679 ns   1033245696 bytes_per_second=2.74383Ti/s
BM_format_string<wchar_t>/1024         0.576 ns        0.575 ns   1219777536 bytes_per_second=6.48343Ti/s
BM_format_string<wchar_t>/2048         0.515 ns        0.514 ns   1361629184 bytes_per_second=14.4881Ti/s
BM_format_string<wchar_t>/4096         0.546 ns        0.545 ns   1285427200 bytes_per_second=27.3342Ti/s
BM_format_string<wchar_t>/8192         0.550 ns        0.548 ns   1277042688 bytes_per_second=54.3343Ti/s
BM_format_string<wchar_t>/16384        0.583 ns        0.581 ns   1203879936 bytes_per_second=102.544Ti/s
BM_format_string<wchar_t>/32768        0.640 ns        0.638 ns   1095139328 bytes_per_second=186.82Ti/s
BM_format_string<wchar_t>/65536        0.642 ns        0.640 ns   1093337088 bytes_per_second=372.283Ti/s
BM_format_string<wchar_t>/131072       0.655 ns        0.654 ns   1070596096 bytes_per_second=729.428Ti/s
BM_format_string<wchar_t>/262144        2.68 ns         2.67 ns    262406144 bytes_per_second=357.446Ti/s
BM_format_string<wchar_t>/524288        2.13 ns         2.13 ns    330301440 bytes_per_second=897.574Ti/s
BM_format_string<wchar_t>/1048576       2.44 ns         2.43 ns    288358400 bytes_per_second=1.53149Pi/s

After
--------------------------------------------------------------------------------------------
Benchmark                                  Time             CPU   Iterations UserCounters...
--------------------------------------------------------------------------------------------
BM_format_string<char>/1                49.3 ns         49.1 ns     14230742 bytes_per_second=19.4054Mi/s
BM_format_string<char>/2                24.8 ns         24.8 ns     28253114 bytes_per_second=77.0465Mi/s
BM_format_string<char>/4                12.4 ns         12.4 ns     56381440 bytes_per_second=307.462Mi/s
BM_format_string<char>/8                6.23 ns         6.21 ns    112951232 bytes_per_second=1.19924Gi/s
BM_format_string<char>/16               3.10 ns         3.09 ns    225822496 bytes_per_second=4.81566Gi/s
BM_format_string<char>/32               1.98 ns         1.98 ns    354208192 bytes_per_second=15.0825Gi/s
BM_format_string<char>/64              0.990 ns        0.987 ns    714296384 bytes_per_second=60.3689Gi/s
BM_format_string<char>/128             0.504 ns        0.503 ns   1399988480 bytes_per_second=237.144Gi/s
BM_format_string<char>/256             0.335 ns        0.334 ns   2084828928 bytes_per_second=712.859Gi/s
BM_format_string<char>/512             0.187 ns        0.186 ns   3760082432 bytes_per_second=2.50102Ti/s
BM_format_string<char>/1024            0.109 ns        0.108 ns   6455339008 bytes_per_second=8.59552Ti/s
BM_format_string<char>/2048            0.080 ns        0.080 ns   8754006016 bytes_per_second=23.2731Ti/s
BM_format_string<char>/4096            0.051 ns        0.051 ns   13786701824 bytes_per_second=73.4088Ti/s
BM_format_string<char>/8192            0.042 ns        0.042 ns   16851435520 bytes_per_second=178.737Ti/s
BM_format_string<char>/16384           0.122 ns        0.122 ns   5746589696 bytes_per_second=122.029Ti/s
BM_format_string<char>/32768           0.107 ns        0.106 ns   6571687936 bytes_per_second=280.122Ti/s
BM_format_string<char>/65536           0.102 ns        0.102 ns   6876626944 bytes_per_second=584.381Ti/s
BM_format_string<char>/131072          0.106 ns        0.105 ns   6643122176 bytes_per_second=1.10413Pi/s
BM_format_string<char>/262144          0.589 ns        0.587 ns   1189609472 bytes_per_second=406.438Ti/s
BM_format_string<char>/524288          0.644 ns        0.642 ns   1088946176 bytes_per_second=743.064Ti/s
BM_format_string<char>/1048576         0.672 ns        0.670 ns   1039138816 bytes_per_second=1.38968Pi/s
BM_format_string<wchar_t>/1             48.7 ns         48.6 ns     14423178 bytes_per_second=78.5263Mi/s
BM_format_string<wchar_t>/2             24.4 ns         24.3 ns     28831748 bytes_per_second=313.869Mi/s
BM_format_string<wchar_t>/4             12.2 ns         12.2 ns     57661220 bytes_per_second=1.2253Gi/s
BM_format_string<wchar_t>/8             7.81 ns         7.79 ns     89887592 bytes_per_second=3.82675Gi/s
BM_format_string<wchar_t>/16            3.88 ns         3.87 ns    180450176 bytes_per_second=15.418Gi/s
BM_format_string<wchar_t>/32            1.98 ns         1.98 ns    354046112 bytes_per_second=60.3262Gi/s
BM_format_string<wchar_t>/64            1.02 ns         1.01 ns    689511680 bytes_per_second=234.906Gi/s
BM_format_string<wchar_t>/128          0.577 ns        0.576 ns   1215361408 bytes_per_second=828.297Gi/s
BM_format_string<wchar_t>/256          0.804 ns        0.802 ns    872249088 bytes_per_second=1.16111Ti/s
BM_format_string<wchar_t>/512          0.642 ns        0.641 ns   1093858304 bytes_per_second=2.90766Ti/s
BM_format_string<wchar_t>/1024         0.517 ns        0.516 ns   1354798080 bytes_per_second=7.21845Ti/s
BM_format_string<wchar_t>/2048         0.469 ns        0.467 ns   1491910656 bytes_per_second=15.9386Ti/s
BM_format_string<wchar_t>/4096         0.794 ns        0.792 ns    883822592 bytes_per_second=18.8156Ti/s
BM_format_string<wchar_t>/8192         0.722 ns        0.720 ns    971718656 bytes_per_second=41.3996Ti/s
BM_format_string<wchar_t>/16384        0.703 ns        0.701 ns    998031360 bytes_per_second=85.0369Ti/s
BM_format_string<wchar_t>/32768        0.724 ns        0.720 ns    971538432 bytes_per_second=165.467Ti/s
BM_format_string<wchar_t>/65536        0.745 ns        0.744 ns    941228032 bytes_per_second=320.665Ti/s
BM_format_string<wchar_t>/131072       0.742 ns        0.740 ns    945422336 bytes_per_second=644.032Ti/s
BM_format_string<wchar_t>/262144        2.99 ns         2.98 ns    234881024 bytes_per_second=319.75Ti/s
BM_format_string<wchar_t>/524288        3.31 ns         3.30 ns    212860928 bytes_per_second=578.085Ti/s
BM_format_string<wchar_t>/1048576       2.69 ns         2.68 ns    260046848 bytes_per_second=1.39081Pi/s

Comparison
Benchmark                                           Time             CPU      Time Old      Time New       CPU Old       CPU New
--------------------------------------------------------------------------------------------------------------------------------
BM_format_string<char>/1                         -0.1122         -0.1143            55            49            55            49
BM_format_string<char>/2                         -0.0999         -0.1020            28            25            28            25
BM_format_string<char>/4                         -0.1148         -0.1169            14            12            14            12
BM_format_string<char>/8                         -0.1186         -0.1207             7             6             7             6
BM_format_string<char>/16                        -0.1222         -0.1243             4             3             4             3
BM_format_string<char>/32                        -0.1417         -0.1438             2             2             2             2
BM_format_string<char>/64                        -0.1407         -0.1427             1             1             1             1
BM_format_string<char>/128                       -0.1559         -0.1579             1             1             1             1
BM_format_string<char>/256                       +0.0249         +0.0222             0             0             0             0
BM_format_string<char>/512                       -0.2473         -0.2491             0             0             0             0
BM_format_string<char>/1024                      -0.4661         -0.4674             0             0             0             0
BM_format_string<char>/2048                      -0.5096         -0.5111             0             0             0             0
BM_format_string<char>/4096                      -0.6278         -0.6287             0             0             0             0
BM_format_string<char>/8192                      -0.6674         -0.6683             0             0             0             0
BM_format_string<char>/16384                     -0.1005         -0.1027             0             0             0             0
BM_format_string<char>/32768                     -0.2127         -0.2147             0             0             0             0
BM_format_string<char>/65536                     -0.5796         -0.5781             0             0             0             0
BM_format_string<char>/131072                    -0.7844         -0.7844             0             0             0             0
BM_format_string<char>/262144                    -0.0073         -0.0086             1             1             1             1
BM_format_string<char>/524288                    +0.0017         +0.0005             1             1             1             1
BM_format_string<char>/1048576                   +0.0039         +0.0037             1             1             1             1
BM_format_string<wchar_t>/1                      -0.1304         -0.1307            56            49            56            49
BM_format_string<wchar_t>/2                      -0.1285         -0.1286            28            24            28            24
BM_format_string<wchar_t>/4                      -0.1288         -0.1288            14            12            14            12
BM_format_string<wchar_t>/8                      -0.1547         -0.1547             9             8             9             8
BM_format_string<wchar_t>/16                     -0.1681         -0.1681             5             4             5             4
BM_format_string<wchar_t>/32                     -0.1579         -0.1580             2             2             2             2
BM_format_string<wchar_t>/64                     -0.2443         -0.2444             1             1             1             1
BM_format_string<wchar_t>/128                    -0.4400         -0.4399             1             1             1             1
BM_format_string<wchar_t>/256                    -0.0535         -0.0535             1             1             1             1
BM_format_string<wchar_t>/512                    -0.0563         -0.0563             1             1             1             1
BM_format_string<wchar_t>/1024                   -0.1018         -0.1018             1             1             1             1
BM_format_string<wchar_t>/2048                   -0.0910         -0.0910             1             0             1             0
BM_format_string<wchar_t>/4096                   +0.4528         +0.4527             1             1             1             1
BM_format_string<wchar_t>/8192                   +0.3121         +0.3124             1             1             1             1
BM_format_string<wchar_t>/16384                  +0.2059         +0.2059             1             1             1             1
BM_format_string<wchar_t>/32768                  +0.1316         +0.1290             1             1             1             1
BM_format_string<wchar_t>/65536                  +0.1604         +0.1610             1             1             1             1
BM_format_string<wchar_t>/131072                 +0.1326         +0.1326             1             1             1             1
BM_format_string<wchar_t>/262144                 +0.1181         +0.1179             3             3             3             3
BM_format_string<wchar_t>/524288                 +0.5515         +0.5527             2             3             2             3
BM_format_string<wchar_t>/1048576                +0.1007         +0.1011             2             3             2             3
OVERALL_GEOMEAN                                  -0.1685         -0.1693             0             0             0             0
@mordante mordante force-pushed the users/mordante/format_performance__format branch from 890a5c8 to a3acb85 Compare August 3, 2024 12:06
Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, I think we should behave more like std::vector and not assume that elements between [size(), capacity()) are already initialized. IMO this is a simpler mental model that is consistent with std::vector and I don't think we leave anything on the table by doing that.

Comment on lines +67 to +68
/// - The class constructor stores a function pointer to a grow function and a
/// type-erased pointer to the object that does the grow.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// - The class constructor stores a function pointer to a grow function and a
/// type-erased pointer to the object that does the grow.
/// - The class constructor stores a function pointer to a "grow" function and a
/// type-erased pointer to the object that should be grown.

Comment on lines +99 to +100
/// - Contains the number of code units that are requested to be written.
/// This number is returned to the user of format_to_n.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// - Contains the number of code units that are requested to be written.
/// This number is returned to the user of format_to_n.
/// - Contains the number of code units that were actually written.
/// This number is returned to the user of format_to_n.

Comment on lines +101 to +102
/// - The write functions call objects __request_write member function.
/// This function:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// - The write functions call objects __request_write member function.
/// This function:
/// - The write functions call the object's __request_write member function.
/// This function:

Comment on lines +108 to +116
/// - __ptr_ the start of the buffer.
/// - __capacity_ the number of code units that can be written.
/// This means [__ptr_, __ptr_ + __capacity_) is a valid range to write to.
/// - __size_ the number of code units written in the buffer. The next code
/// unit will be written at __ptr_ + __size_. This __size_ may NOT contain
/// the total number of code units written by the __output_buffer. Whether or
/// not it does depends on the sub-class used. Typically the total number of
/// code units written is not interesting. It is interesting for format_to_n
/// which has its own way to track this number.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// - __ptr_ the start of the buffer.
/// - __capacity_ the number of code units that can be written.
/// This means [__ptr_, __ptr_ + __capacity_) is a valid range to write to.
/// - __size_ the number of code units written in the buffer. The next code
/// unit will be written at __ptr_ + __size_. This __size_ may NOT contain
/// the total number of code units written by the __output_buffer. Whether or
/// not it does depends on the sub-class used. Typically the total number of
/// code units written is not interesting. It is interesting for format_to_n
/// which has its own way to track this number.
/// - __ptr_
/// The start of the buffer.
/// - __capacity_
/// The number of code units that can be written.
/// This means [__ptr_, __ptr_ + __capacity_) is a valid range to write to.
/// - __size_
/// The number of code units written in the buffer. The next code
/// unit will be written at __ptr_ + __size_. This __size_ may NOT contain
/// the total number of code units written by the __output_buffer. Whether or
/// not it does depends on the sub-class used. Typically the total number of
/// code units written is not interesting. It is interesting for format_to_n
/// which has its own way to track this number.

Breaking the line makes it easier to see that the first word is the name of the member.

/// __output_buffer<_CharT>& __buffer, size_t __code_units);
///
/// This function is called when a write function writes more code units than
/// the buffer' available space. When an __max_output_size object is provided
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// the buffer' available space. When an __max_output_size object is provided
/// the buffer's available space. When an __max_output_size object is provided

}

// New LLVM-20 function.
_LIBCPP_HIDE_FROM_ABI void __buffer_flused() { __size_ = 0; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_LIBCPP_HIDE_FROM_ABI void __buffer_flused() { __size_ = 0; }
_LIBCPP_HIDE_FROM_ABI void __buffer_flushed() { __size_ = 0; }

Comment on lines +699 to +710
auto __guard = std::__make_exception_guard([&] {
allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count);
});
// This shouldn't throw, but just to be safe. Note that at -O1 this
// guard is optimized away so there is no runtime overhead.
new (__result.ptr) _CharT[__result.count];
std::copy_n(__ptr_, this->__size(), __result.ptr);
__guard.__complete();
if (__ptr_ != __buffer_) {
ranges::destroy_n(__ptr_, this->__capacity());
allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, this->__capacity());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto __guard = std::__make_exception_guard([&] {
allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count);
});
// This shouldn't throw, but just to be safe. Note that at -O1 this
// guard is optimized away so there is no runtime overhead.
new (__result.ptr) _CharT[__result.count];
std::copy_n(__ptr_, this->__size(), __result.ptr);
__guard.__complete();
if (__ptr_ != __buffer_) {
ranges::destroy_n(__ptr_, this->__capacity());
allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, this->__capacity());
}
auto __guard = std::__make_exception_guard([&] {
allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count);
});
// This shouldn't throw, but just to be safe. Note that at -O1 this
// guard is optimized away so there is no runtime overhead.
std::__uninitialized_allocator_relocate(__alloc_, __ptr_, __ptr_ + this->__size(), __result.ptr);
__guard.__complete();
if (__ptr_ != __buffer_) {
allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, this->__capacity());
}

Comment on lines +682 to +685
// At the moment the allocator is hard-code. There might be reasons to have
// an allocator trait in the future. This ensures forward compatibility.
using _Alloc = allocator<_CharT>;
_LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we hardcode the allocator, I would simply not use one. This would simplify business with construct_at & friends too.


_LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return std::back_insert_iterator{*this}; }

// Used in std::back_insert_iterator.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I think it should be

  _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) {
    std::__construct_at(__ptr_ + __size_, __c);
    ++__size_;
     // Profiling showed flushing after adding is more efficient than flushing
     // when entering the function.
     if (__size_ == __capacity_)
       __flush(0);
   }

std::vformat_to(std::back_inserter(__res), __fmt, __args);
return __res;
__format::__allocating_buffer<char> __buffer;
std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove an include since you don't mention back_inserter directly anymore?

// Since allocating is expensive the class has a small internal buffer. When
// its capacity is exceeded a dynamic buffer will be allocated.
static constexpr size_t __buffer_size_ = 256;
_CharT __buffer_[__buffer_size_];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_CharT __buffer_[__buffer_size_];
std::byte __buffer_[__buffer_size_ * sizeof(_CharT)];

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After looking at the patches later in the series, I am not certain these comments about implementing this as vector (i.e. elements beyond size() not having their lifetime started yet) is the best approach. I think your current approach may be better.

However, I think that the usage of back_insert_iterator<__output_buffer> + __output_buffer::push_back is misleading -- that's what caused me to think this should behave as a vector when in reality this is a different beast. If instead we had a method called __push_back (or __insert_back) and we used our own small iterator type to output to the buffer, it would make the design of this class clearer. It would also put __push_back/__insert_back on the same level as the other "insertion" functions like __fill and others. So IMO the current design might be fine lifetime-wise, but I think it would be nice to avoid using back_insert_iterator<__output_buffer> since __output_buffer is fundamentally not a container.

I understand that using back_inserter greatly simplifies the boilerplate needed, but IMO that's still the right design.

string __res;
std::vformat_to(std::back_inserter(__res), __fmt, __args);
return __res;
__format::__allocating_buffer<char> __buffer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would actually be really nice if vformat_to(std::back_inserter(string), ...) were just as performant as using the allocating buffer. It seems to me that if using the __allocating_buffer directly is faster, there may be a problem with next patch's buffer_selector which would basically be picking a less efficient approach for the case of std::back_inserter<std::string>.

///
/// The latter option allows formatted_size to use the output buffer without
/// ever writing anything to the buffer.
template <__fmt_char_type _CharT>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
template <__fmt_char_type _CharT>
template <contiguous_iterator _BufferIterator, __fmt_char_type _CharT>

This would allow the derived classes to pass down their actual iterator types, which would make it possible to e.g. retain bounds information when we have some in the iterator.


// New LLVM-20 function.
[[nodiscard]]
_LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, __prepare_write_type __prepare_write)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then this would become

Suggested change
_LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, __prepare_write_type __prepare_write)
_LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_BufferIterator __ptr, size_t __capacity, __prepare_write_type __prepare_write)

@mordante mordante force-pushed the users/mordante/format_performance__c_string_optimization branch from f46ff67 to 9c7c298 Compare September 17, 2024 15:22
@mordante mordante force-pushed the users/mordante/format_performance__c_string_optimization branch from 9c7c298 to efa7aff Compare October 6, 2024 16:26
Base automatically changed from users/mordante/format_performance__c_string_optimization to main October 6, 2024 19:20
@mordante
Copy link
Member Author

Abandoned, done in a different patch.

@mordante mordante closed this Jan 25, 2025
@mordante mordante deleted the users/mordante/format_performance__format branch January 25, 2025 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants