Skip to content

Conversation

@Marius-Juston
Copy link
Contributor

@Marius-JustonMarius-Juston commented Mar 31, 2025

Minor optimization to @AA-Turner#131792 where you compute the min and max of the non_blank_lines simultaneously, removes additional use of line.isspace() as well.

Benchmarkrawnew
raw_text: "abc \t"2.91 ms3.33 ms: 1.15x slower
raw_text: " "4.31 ms4.17 ms: 1.03x faster
raw_text: " \t abc"4.04 ms4.40 ms: 1.09x slower
raw_text: " \t abc \t "4.08 ms4.40 ms: 1.08x slower
raw_text: 1000 spaces34.9 ms27.9 ms: 1.25x faster
Basic indented text with empty lines1.88 us1.82 us: 1.03x faster
Text with mixed indentation and blank lines1.85 us1.79 us: 1.03x faster
No indentation (edge case)1.24 us1.14 us: 1.09x faster
Only blank lines958 ns641 ns: 1.49x faster
Edge case: No common prefix to remove1.09 us993 ns: 1.10x faster
Edge case: Single indented line998 ns855 ns: 1.17x faster
Edge case: Single indented line only631 ns432 ns: 1.46x faster
Edge case: Empty text89.3 ns81.0 ns: 1.10x faster
no_indent2.57 us2.50 us: 1.03x faster
mixed10.4 us10.9 us: 1.05x slower
large_text77.7 us85.7 us: 1.10x slower
whitespace_only859 ns599 ns: 1.43x faster
Geometric mean(ref)1.08x faster

@ghost
Copy link

ghost commented Mar 31, 2025

All commit authors signed the Contributor License Agreement.
CLA signed

@AA-Turner
Copy link
Member

It seems for the benchmarks handling large text, there's a consistent slowdown. Could you plot a chart of running the function with inputs of different sizes? Perhaps take the unicodeobject file and profile the first 500 lines, then the first 1000, 1500, etc, for this PR and the version using min/max.

A

@Marius-Juston
Copy link
ContributorAuthor

It stays a consistently slower by 5-8% except for long lines test

Benchmarkraw_scalenew_scale
lines: 500 raw_text: no prefix93.0 us99.2 us: 1.07x slower
lines: 1000 raw_text: no prefix193 us203 us: 1.05x slower
lines: 1500 raw_text: no prefix289 us306 us: 1.06x slower
lines: 2000 raw_text: no prefix387 us415 us: 1.07x slower
lines: 2500 raw_text: no prefix493 us521 us: 1.06x slower
lines: 3000 raw_text: no prefix593 us639 us: 1.08x slower
lines: 3500 raw_text: no prefix697 us738 us: 1.06x slower
lines: 4000 raw_text: no prefix799 us841 us: 1.05x slower
lines: 4500 raw_text: no prefix895 us952 us: 1.06x slower
lines: 5000 raw_text: no prefix1.01 ms1.07 ms: 1.06x slower
lines: 5500 raw_text: no prefix1.10 ms1.18 ms: 1.07x slower
lines: 6000 raw_text: no prefix1.21 ms1.29 ms: 1.07x slower
lines: 6500 raw_text: no prefix1.31 ms1.39 ms: 1.06x slower
lines: 7000 raw_text: no prefix1.43 ms1.52 ms: 1.07x slower
lines: 7500 raw_text: no prefix1.52 ms1.61 ms: 1.06x slower
lines: 8000 raw_text: no prefix1.63 ms1.73 ms: 1.06x slower
lines: 8500 raw_text: no prefix1.71 ms1.81 ms: 1.06x slower
lines: 9000 raw_text: no prefix1.82 ms1.92 ms: 1.05x slower
lines: 9500 raw_text: no prefix1.92 ms2.04 ms: 1.06x slower
lines: 500 raw_text: "abc \t"89.7 us99.2 us: 1.11x slower
lines: 1000 raw_text: "abc \t"175 us201 us: 1.15x slower
lines: 1500 raw_text: "abc \t"265 us300 us: 1.13x slower
lines: 2000 raw_text: "abc \t"354 us404 us: 1.14x slower
lines: 2500 raw_text: "abc \t"446 us523 us: 1.17x slower
lines: 3000 raw_text: "abc \t"537 us609 us: 1.14x slower
lines: 3500 raw_text: "abc \t"628 us708 us: 1.13x slower
lines: 4000 raw_text: "abc \t"718 us813 us: 1.13x slower
lines: 4500 raw_text: "abc \t"803 us920 us: 1.15x slower
lines: 5000 raw_text: "abc \t"908 us1.02 ms: 1.13x slower
lines: 5500 raw_text: "abc \t"988 us1.13 ms: 1.14x slower
lines: 6000 raw_text: "abc \t"1.09 ms1.26 ms: 1.16x slower
lines: 6500 raw_text: "abc \t"1.18 ms1.33 ms: 1.13x slower
lines: 7000 raw_text: "abc \t"1.28 ms1.44 ms: 1.12x slower
lines: 7500 raw_text: "abc \t"1.37 ms1.54 ms: 1.13x slower
lines: 8000 raw_text: "abc \t"1.47 ms1.63 ms: 1.11x slower
lines: 8500 raw_text: "abc \t"1.54 ms1.75 ms: 1.14x slower
lines: 9000 raw_text: "abc \t"1.64 ms1.88 ms: 1.15x slower
lines: 9500 raw_text: "abc \t"1.72 ms1.93 ms: 1.12x slower
lines: 500 raw_text: " "104 us108 us: 1.04x slower
lines: 1000 raw_text: " "213 us221 us: 1.04x slower
lines: 1500 raw_text: " "320 us336 us: 1.05x slower
lines: 2000 raw_text: " "435 us473 us: 1.09x slower
lines: 2500 raw_text: " "544 us563 us: 1.04x slower
lines: 3000 raw_text: " "658 us684 us: 1.04x slower
lines: 3500 raw_text: " "767 us798 us: 1.04x slower
lines: 4000 raw_text: " "884 us916 us: 1.04x slower
lines: 4500 raw_text: " "995 us1.05 ms: 1.05x slower
lines: 5000 raw_text: " "1.11 ms1.22 ms: 1.10x slower
lines: 5500 raw_text: " "1.22 ms1.28 ms: 1.05x slower
lines: 6000 raw_text: " "1.34 ms1.40 ms: 1.04x slower
lines: 6500 raw_text: " "1.46 ms1.51 ms: 1.04x slower
lines: 7000 raw_text: " "1.57 ms1.63 ms: 1.04x slower
lines: 7500 raw_text: " "1.68 ms1.74 ms: 1.04x slower
lines: 8000 raw_text: " "1.79 ms1.86 ms: 1.04x slower
lines: 8500 raw_text: " "1.93 ms1.98 ms: 1.03x slower
lines: 9000 raw_text: " "2.02 ms2.08 ms: 1.03x slower
lines: 9500 raw_text: " "2.12 ms2.21 ms: 1.04x slower
lines: 500 raw_text: "\t"101 us106 us: 1.05x slower
lines: 1000 raw_text: "\t"206 us217 us: 1.05x slower
lines: 1500 raw_text: "\t"318 us331 us: 1.04x slower
lines: 2000 raw_text: "\t"427 us443 us: 1.04x slower
lines: 2500 raw_text: "\t"537 us569 us: 1.06x slower
lines: 3000 raw_text: "\t"644 us677 us: 1.05x slower
lines: 3500 raw_text: "\t"758 us790 us: 1.04x slower
lines: 4000 raw_text: "\t"866 us908 us: 1.05x slower
lines: 4500 raw_text: "\t"981 us1.03 ms: 1.05x slower
lines: 5000 raw_text: "\t"1.10 ms1.15 ms: 1.05x slower
lines: 5500 raw_text: "\t"1.20 ms1.26 ms: 1.05x slower
lines: 6000 raw_text: "\t"1.32 ms1.38 ms: 1.04x slower
lines: 6500 raw_text: "\t"1.43 ms1.50 ms: 1.06x slower
lines: 7000 raw_text: "\t"1.55 ms1.62 ms: 1.05x slower
lines: 7500 raw_text: "\t"1.66 ms1.72 ms: 1.04x slower
lines: 8000 raw_text: "\t"1.79 ms1.84 ms: 1.03x slower
lines: 8500 raw_text: "\t"1.91 ms1.97 ms: 1.03x slower
lines: 9000 raw_text: "\t"1.98 ms2.07 ms: 1.04x slower
lines: 9500 raw_text: "\t"2.10 ms2.19 ms: 1.04x slower
lines: 500 raw_text: " \t abc"101 us106 us: 1.05x slower
lines: 1000 raw_text: " \t abc"198 us214 us: 1.08x slower
lines: 1500 raw_text: " \t abc"299 us323 us: 1.08x slower
lines: 2000 raw_text: " \t abc"404 us436 us: 1.08x slower
lines: 2500 raw_text: " \t abc"500 us553 us: 1.11x slower
lines: 3000 raw_text: " \t abc"611 us658 us: 1.08x slower
lines: 3500 raw_text: " \t abc"703 us778 us: 1.11x slower
lines: 4000 raw_text: " \t abc"806 us880 us: 1.09x slower
lines: 4500 raw_text: " \t abc"916 us1.01 ms: 1.10x slower
lines: 5000 raw_text: " \t abc"1.01 ms1.12 ms: 1.10x slower
lines: 5500 raw_text: " \t abc"1.12 ms1.23 ms: 1.10x slower
lines: 6000 raw_text: " \t abc"1.22 ms1.35 ms: 1.10x slower
lines: 6500 raw_text: " \t abc"1.33 ms1.47 ms: 1.11x slower
lines: 7000 raw_text: " \t abc"1.43 ms1.56 ms: 1.09x slower
lines: 7500 raw_text: " \t abc"1.52 ms1.67 ms: 1.10x slower
lines: 8000 raw_text: " \t abc"1.64 ms1.77 ms: 1.08x slower
lines: 8500 raw_text: " \t abc"1.72 ms1.88 ms: 1.10x slower
lines: 9000 raw_text: " \t abc"1.83 ms2.00 ms: 1.09x slower
lines: 9500 raw_text: " \t abc"2.28 ms2.49 ms: 1.09x slower
lines: 500 raw_text: " \t abc \t "102 us115 us: 1.13x slower
lines: 1000 raw_text: " \t abc \t "199 us228 us: 1.15x slower
lines: 1500 raw_text: " \t abc \t "303 us326 us: 1.07x slower
lines: 2000 raw_text: " \t abc \t "400 us438 us: 1.09x slower
lines: 2500 raw_text: " \t abc \t "504 us549 us: 1.09x slower
lines: 3000 raw_text: " \t abc \t "611 us659 us: 1.08x slower
lines: 3500 raw_text: " \t abc \t "715 us768 us: 1.07x slower
lines: 4000 raw_text: " \t abc \t "816 us884 us: 1.08x slower
lines: 4500 raw_text: " \t abc \t "912 us1.01 ms: 1.10x slower
lines: 5000 raw_text: " \t abc \t "1.03 ms1.12 ms: 1.09x slower
lines: 5500 raw_text: " \t abc \t "1.13 ms1.24 ms: 1.10x slower
lines: 6000 raw_text: " \t abc \t "1.23 ms1.35 ms: 1.09x slower
lines: 6500 raw_text: " \t abc \t "1.33 ms1.45 ms: 1.09x slower
lines: 7000 raw_text: " \t abc \t "1.44 ms1.56 ms: 1.08x slower
lines: 7500 raw_text: " \t abc \t "1.54 ms1.67 ms: 1.08x slower
lines: 8000 raw_text: " \t abc \t "1.64 ms1.78 ms: 1.09x slower
lines: 8500 raw_text: " \t abc \t "1.75 ms1.91 ms: 1.09x slower
lines: 9000 raw_text: " \t abc \t "2.19 ms2.30 ms: 1.05x slower
lines: 9500 raw_text: " \t abc \t "2.33 ms2.53 ms: 1.08x slower
lines: 500 raw_text: 1000 spaces906 us680 us: 1.33x faster
lines: 1000 raw_text: 1000 spaces1.79 ms1.31 ms: 1.36x faster
lines: 1500 raw_text: 1000 spaces2.67 ms1.95 ms: 1.37x faster
lines: 2000 raw_text: 1000 spaces3.55 ms2.62 ms: 1.36x faster
lines: 2500 raw_text: 1000 spaces4.42 ms3.25 ms: 1.36x faster
lines: 3000 raw_text: 1000 spaces5.63 ms3.88 ms: 1.45x faster
lines: 3500 raw_text: 1000 spaces6.67 ms4.51 ms: 1.48x faster
lines: 4000 raw_text: 1000 spaces7.73 ms5.60 ms: 1.38x faster
lines: 4500 raw_text: 1000 spaces8.83 ms6.46 ms: 1.37x faster
lines: 5000 raw_text: 1000 spaces9.91 ms7.28 ms: 1.36x faster
lines: 5500 raw_text: 1000 spaces11.0 ms8.12 ms: 1.35x faster
lines: 6000 raw_text: 1000 spaces12.0 ms9.02 ms: 1.34x faster
lines: 6500 raw_text: 1000 spaces13.1 ms9.76 ms: 1.34x faster
lines: 7000 raw_text: 1000 spaces14.2 ms10.7 ms: 1.33x faster
lines: 7500 raw_text: 1000 spaces15.5 ms11.5 ms: 1.35x faster
lines: 8000 raw_text: 1000 spaces16.5 ms12.3 ms: 1.34x faster
lines: 8500 raw_text: 1000 spaces17.6 ms13.4 ms: 1.31x faster
lines: 9000 raw_text: 1000 spaces18.8 ms14.1 ms: 1.33x faster
lines: 9500 raw_text: 1000 spaces20.0 ms15.0 ms: 1.33x faster
Geometric mean(ref)1.02x slower

@Marius-Juston
Copy link
ContributorAuthor

From additional testing, this way is slightly faster in the ranges where the lines are between 1-18.

Benchmarkraw_scale_2new_scale_2
lines: 2 raw_text: no prefix890 ns764 ns: 1.16x faster
lines: 4 raw_text: no prefix1.25 us1.16 us: 1.08x faster
lines: 6 raw_text: no prefix1.56 us1.47 us: 1.06x faster
lines: 8 raw_text: no prefix1.84 us1.77 us: 1.04x faster
lines: 10 raw_text: no prefix2.14 us2.08 us: 1.03x faster
lines: 20 raw_text: no prefix3.80 us3.86 us: 1.02x slower
lines: 22 raw_text: no prefix4.21 us4.30 us: 1.02x slower
lines: 24 raw_text: no prefix4.64 us4.77 us: 1.03x slower
lines: 26 raw_text: no prefix5.10 us5.19 us: 1.02x slower
lines: 28 raw_text: no prefix5.43 us5.52 us: 1.02x slower
lines: 30 raw_text: no prefix5.73 us5.81 us: 1.01x slower
lines: 32 raw_text: no prefix6.20 us6.30 us: 1.02x slower
lines: 36 raw_text: no prefix6.95 us7.14 us: 1.03x slower
lines: 38 raw_text: no prefix7.27 us7.49 us: 1.03x slower
lines: 40 raw_text: no prefix7.55 us7.73 us: 1.02x slower
lines: 42 raw_text: no prefix7.89 us8.13 us: 1.03x slower
lines: 44 raw_text: no prefix8.31 us8.54 us: 1.03x slower
lines: 46 raw_text: no prefix8.78 us8.92 us: 1.02x slower
lines: 48 raw_text: no prefix9.17 us9.41 us: 1.03x slower
lines: 2 raw_text: "abc \t"894 ns765 ns: 1.17x faster
lines: 4 raw_text: "abc \t"1.29 us1.21 us: 1.07x faster
lines: 6 raw_text: "abc \t"1.60 us1.52 us: 1.05x faster
lines: 8 raw_text: "abc \t"1.88 us1.80 us: 1.04x faster
lines: 10 raw_text: "abc \t"2.18 us2.12 us: 1.03x faster
lines: 12 raw_text: "abc \t"2.59 us2.54 us: 1.02x faster
lines: 14 raw_text: "abc \t"2.97 us2.87 us: 1.03x faster
lines: 16 raw_text: "abc \t"3.19 us3.16 us: 1.01x faster
lines: 22 raw_text: "abc \t"4.32 us4.38 us: 1.01x slower
lines: 24 raw_text: "abc \t"4.78 us4.91 us: 1.03x slower
lines: 26 raw_text: "abc \t"5.20 us5.30 us: 1.02x slower
lines: 28 raw_text: "abc \t"5.57 us5.71 us: 1.03x slower
lines: 30 raw_text: "abc \t"5.87 us6.01 us: 1.02x slower
lines: 32 raw_text: "abc \t"6.28 us6.52 us: 1.04x slower
lines: 34 raw_text: "abc \t"6.68 us6.86 us: 1.03x slower
lines: 36 raw_text: "abc \t"7.07 us7.33 us: 1.04x slower
lines: 42 raw_text: "abc \t"8.09 us8.31 us: 1.03x slower
lines: 44 raw_text: "abc \t"8.45 us8.77 us: 1.04x slower
lines: 46 raw_text: "abc \t"8.89 us9.14 us: 1.03x slower
lines: 48 raw_text: "abc \t"9.20 us9.63 us: 1.05x slower
lines: 2 raw_text: " "1.13 us999 ns: 1.13x faster
lines: 4 raw_text: " "1.55 us1.44 us: 1.08x faster
lines: 6 raw_text: " "1.86 us1.78 us: 1.04x faster
lines: 8 raw_text: " "2.19 us2.08 us: 1.05x faster
lines: 10 raw_text: " "2.49 us2.41 us: 1.03x faster
lines: 12 raw_text: " "2.88 us2.86 us: 1.01x faster
lines: 18 raw_text: " "4.27 us4.00 us: 1.07x faster
lines: 20 raw_text: " "4.48 us4.33 us: 1.03x faster
lines: 22 raw_text: " "4.75 us4.81 us: 1.01x slower
lines: 26 raw_text: " "5.69 us5.76 us: 1.01x slower
lines: 30 raw_text: " "6.37 us6.49 us: 1.02x slower
lines: 32 raw_text: " "6.84 us7.08 us: 1.04x slower
lines: 34 raw_text: " "7.27 us7.51 us: 1.03x slower
lines: 36 raw_text: " "7.71 us7.86 us: 1.02x slower
lines: 2 raw_text: "\t"1.07 us833 ns: 1.28x faster
lines: 4 raw_text: "\t"1.37 us1.28 us: 1.07x faster
lines: 6 raw_text: "\t"1.69 us1.60 us: 1.06x faster
lines: 8 raw_text: "\t"1.99 us1.89 us: 1.06x faster
lines: 10 raw_text: "\t"2.28 us2.24 us: 1.02x faster
lines: 20 raw_text: "\t"4.10 us4.21 us: 1.03x slower
lines: 22 raw_text: "\t"4.52 us4.58 us: 1.01x slower
lines: 24 raw_text: "\t"4.95 us5.03 us: 1.02x slower
lines: 28 raw_text: "\t"5.85 us5.96 us: 1.02x slower
lines: 34 raw_text: "\t"7.02 us7.30 us: 1.04x slower
lines: 36 raw_text: "\t"7.43 us7.65 us: 1.03x slower
lines: 38 raw_text: "\t"7.80 us8.02 us: 1.03x slower
lines: 40 raw_text: "\t"8.09 us8.32 us: 1.03x slower
lines: 42 raw_text: "\t"8.49 us8.78 us: 1.03x slower
lines: 44 raw_text: "\t"8.91 us9.31 us: 1.04x slower
lines: 46 raw_text: "\t"9.36 us9.63 us: 1.03x slower
lines: 48 raw_text: "\t"9.75 us10.0 us: 1.03x slower
lines: 2 raw_text: " \t abc"1.14 us993 ns: 1.15x faster
lines: 4 raw_text: " \t abc"1.57 us1.47 us: 1.07x faster
lines: 6 raw_text: " \t abc"1.90 us1.79 us: 1.06x faster
lines: 8 raw_text: " \t abc"2.22 us2.09 us: 1.06x faster
lines: 10 raw_text: " \t abc"2.51 us2.43 us: 1.03x faster
lines: 12 raw_text: " \t abc"2.96 us2.89 us: 1.02x faster
lines: 14 raw_text: " \t abc"3.39 us3.27 us: 1.04x faster
lines: 20 raw_text: " \t abc"4.44 us4.36 us: 1.02x faster
lines: 24 raw_text: " \t abc"5.30 us5.38 us: 1.01x slower
lines: 30 raw_text: " \t abc"6.47 us6.53 us: 1.01x slower
lines: 38 raw_text: " \t abc"8.15 us8.33 us: 1.02x slower
lines: 40 raw_text: " \t abc"8.46 us8.58 us: 1.01x slower
lines: 42 raw_text: " \t abc"8.88 us9.10 us: 1.02x slower
lines: 44 raw_text: " \t abc"9.26 us9.46 us: 1.02x slower
lines: 46 raw_text: " \t abc"9.73 us9.91 us: 1.02x slower
lines: 48 raw_text: " \t abc"10.2 us10.4 us: 1.03x slower
lines: 2 raw_text: " \t abc \t "1.15 us997 ns: 1.16x faster
lines: 4 raw_text: " \t abc \t "1.56 us1.48 us: 1.06x faster
lines: 6 raw_text: " \t abc \t "1.90 us1.80 us: 1.06x faster
lines: 8 raw_text: " \t abc \t "2.27 us2.16 us: 1.05x faster
lines: 10 raw_text: " \t abc \t "2.57 us2.46 us: 1.05x faster
lines: 12 raw_text: " \t abc \t "3.01 us2.94 us: 1.02x faster
lines: 14 raw_text: " \t abc \t "3.37 us3.28 us: 1.03x faster
lines: 22 raw_text: " \t abc \t "4.83 us4.97 us: 1.03x slower
lines: 26 raw_text: " \t abc \t "5.82 us5.93 us: 1.02x slower
lines: 30 raw_text: " \t abc \t "6.50 us6.67 us: 1.03x slower
lines: 36 raw_text: " \t abc \t "7.89 us8.04 us: 1.02x slower
Geometric mean(ref)1.01x faster

after analyzing all the function documentation in the Python codebase the average documentation length seems to be the following https://gist.github.com/Marius-Juston/08c574901317ee40837ab87ce0855685:

StatDoc Length
Min2
Max99
Mean10.361825192802057
Median7

( excluding all 1 line comments )

so technically, this implementation is slightly faster for the average documentation length ( now is this performance increase really worth it, no probably not lol )

Lib/textwrap.py Outdated
l1 = min(non_blank_lines, default='')
l2 = max(non_blank_lines, default='')
margin = 0
l1 = None
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
l1=None
l1=''

You can then skip the is None check in the loop. Similar for l2 (but you have to pick the default with care)

Lib/textwrap.py Outdated
if line and not line.isspace():
if l1 is None or line < l1:
l1 = line
if l2 is None or line > l2:
Copy link
Contributor

Choose a reason for hiding this comment

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

Once you skip the if None check, this if can be an elseif

@picnixz
Copy link
Member

picnixz commented Mar 31, 2025

I'm against this change not only because it's harder to read but also because it only offers an overall <10% speed-up. In general, we accept optimizations exceeding that threshold.

@Marius-Juston
Copy link
ContributorAuthor

@eendebakpt with the new changes:

Benchmarkrawnewnew2
raw_text: "abc \t"2.91 ms3.33 ms: 1.15x slower3.27 ms: 1.12x slower
raw_text: " "4.31 ms4.17 ms: 1.03x faster4.16 ms: 1.03x faster
raw_text: "\t"4.20 msnot significant4.13 ms: 1.02x faster
raw_text: " \t abc"4.04 ms4.40 ms: 1.09x slower4.37 ms: 1.08x slower
raw_text: " \t abc \t "4.08 ms4.40 ms: 1.08x slower4.37 ms: 1.07x slower
raw_text: 1000 spaces34.9 ms27.9 ms: 1.25x faster27.3 ms: 1.28x faster
Basic indented text with empty lines1.88 us1.82 us: 1.03x faster1.83 us: 1.03x faster
Text with mixed indentation and blank lines1.85 us1.79 us: 1.03x faster1.81 us: 1.03x faster
No indentation (edge case)1.24 us1.14 us: 1.09x faster1.12 us: 1.11x faster
Only blank lines958 ns641 ns: 1.49x faster520 ns: 1.84x faster
Edge case: No common prefix to remove1.09 us993 ns: 1.10x faster962 ns: 1.14x faster
Edge case: Single indented line998 ns855 ns: 1.17x faster862 ns: 1.16x faster
Edge case: Single indented line only631 ns432 ns: 1.46x faster334 ns: 1.89x faster
Edge case: Empty text89.3 ns81.0 ns: 1.10x faster78.9 ns: 1.13x faster
no_indent2.57 us2.50 us: 1.03x faster2.44 us: 1.05x faster
mixed10.4 us10.9 us: 1.05x slower10.7 us: 1.03x slower
large_text77.7 us85.7 us: 1.10x slower83.5 us: 1.08x slower
whitespace_only859 ns599 ns: 1.43x faster479 ns: 1.79x faster
Geometric mean(ref)1.08x faster1.13x faster

Small values

Benchmarkraw_scale_2new_scale_2new2_scale_2
lines: 2 raw_text: no prefix890 ns764 ns: 1.16x faster766 ns: 1.16x faster
lines: 4 raw_text: no prefix1.25 us1.16 us: 1.08x faster1.17 us: 1.08x faster
lines: 6 raw_text: no prefix1.56 us1.47 us: 1.06x faster1.49 us: 1.04x faster
lines: 8 raw_text: no prefix1.84 us1.77 us: 1.04x faster1.77 us: 1.04x faster
lines: 10 raw_text: no prefix2.14 us2.08 us: 1.03x faster2.05 us: 1.04x faster
lines: 14 raw_text: no prefix2.82 usnot significant2.73 us: 1.03x faster
lines: 16 raw_text: no prefix3.17 usnot significant3.06 us: 1.04x faster
lines: 18 raw_text: no prefix3.52 usnot significant3.45 us: 1.02x faster
lines: 20 raw_text: no prefix3.80 us3.86 us: 1.02x slower3.74 us: 1.02x faster
lines: 22 raw_text: no prefix4.21 us4.30 us: 1.02x slower4.30 us: 1.02x slower
lines: 24 raw_text: no prefix4.64 us4.77 us: 1.03x slowernot significant
lines: 26 raw_text: no prefix5.10 us5.19 us: 1.02x slowernot significant
lines: 28 raw_text: no prefix5.43 us5.52 us: 1.02x slowernot significant
lines: 30 raw_text: no prefix5.73 us5.81 us: 1.01x slower5.85 us: 1.02x slower
lines: 32 raw_text: no prefix6.20 us6.30 us: 1.02x slowernot significant
lines: 36 raw_text: no prefix6.95 us7.14 us: 1.03x slowernot significant
lines: 38 raw_text: no prefix7.27 us7.49 us: 1.03x slowernot significant
lines: 40 raw_text: no prefix7.55 us7.73 us: 1.02x slowernot significant
lines: 42 raw_text: no prefix7.89 us8.13 us: 1.03x slower8.06 us: 1.02x slower
lines: 44 raw_text: no prefix8.31 us8.54 us: 1.03x slower8.49 us: 1.02x slower
lines: 46 raw_text: no prefix8.78 us8.92 us: 1.02x slowernot significant
lines: 48 raw_text: no prefix9.17 us9.41 us: 1.03x slowernot significant
lines: 2 raw_text: "abc \t"894 ns765 ns: 1.17x faster777 ns: 1.15x faster
lines: 4 raw_text: "abc \t"1.29 us1.21 us: 1.07x faster1.20 us: 1.07x faster
lines: 6 raw_text: "abc \t"1.60 us1.52 us: 1.05x faster1.54 us: 1.04x faster
lines: 8 raw_text: "abc \t"1.88 us1.80 us: 1.04x faster1.79 us: 1.05x faster
lines: 10 raw_text: "abc \t"2.18 us2.12 us: 1.03x faster2.09 us: 1.04x faster
lines: 12 raw_text: "abc \t"2.59 us2.54 us: 1.02x faster2.50 us: 1.03x faster
lines: 14 raw_text: "abc \t"2.97 us2.87 us: 1.03x faster2.84 us: 1.05x faster
lines: 16 raw_text: "abc \t"3.19 us3.16 us: 1.01x fasternot significant
lines: 22 raw_text: "abc \t"4.32 us4.38 us: 1.01x slower4.30 us: 1.01x faster
lines: 24 raw_text: "abc \t"4.78 us4.91 us: 1.03x slowernot significant
lines: 26 raw_text: "abc \t"5.20 us5.30 us: 1.02x slowernot significant
lines: 28 raw_text: "abc \t"5.57 us5.71 us: 1.03x slowernot significant
lines: 30 raw_text: "abc \t"5.87 us6.01 us: 1.02x slowernot significant
lines: 32 raw_text: "abc \t"6.28 us6.52 us: 1.04x slowernot significant
lines: 34 raw_text: "abc \t"6.68 us6.86 us: 1.03x slower6.88 us: 1.03x slower
lines: 36 raw_text: "abc \t"7.07 us7.33 us: 1.04x slowernot significant
lines: 42 raw_text: "abc \t"8.09 us8.31 us: 1.03x slower8.34 us: 1.03x slower
lines: 44 raw_text: "abc \t"8.45 us8.77 us: 1.04x slower8.61 us: 1.02x slower
lines: 46 raw_text: "abc \t"8.89 us9.14 us: 1.03x slower9.07 us: 1.02x slower
lines: 48 raw_text: "abc \t"9.20 us9.63 us: 1.05x slower9.48 us: 1.03x slower
lines: 2 raw_text: " "1.13 us999 ns: 1.13x faster1.02 us: 1.11x faster
lines: 4 raw_text: " "1.55 us1.44 us: 1.08x faster1.49 us: 1.04x faster
lines: 6 raw_text: " "1.86 us1.78 us: 1.04x fasternot significant
lines: 8 raw_text: " "2.19 us2.08 us: 1.05x faster2.09 us: 1.05x faster
lines: 10 raw_text: " "2.49 us2.41 us: 1.03x fasternot significant
lines: 12 raw_text: " "2.88 us2.86 us: 1.01x fasternot significant
lines: 18 raw_text: " "4.27 us4.00 us: 1.07x faster3.96 us: 1.08x faster
lines: 20 raw_text: " "4.48 us4.33 us: 1.03x faster4.32 us: 1.04x faster
lines: 22 raw_text: " "4.75 us4.81 us: 1.01x slower4.82 us: 1.02x slower
lines: 26 raw_text: " "5.69 us5.76 us: 1.01x slowernot significant
lines: 30 raw_text: " "6.37 us6.49 us: 1.02x slower6.53 us: 1.03x slower
lines: 32 raw_text: " "6.84 us7.08 us: 1.04x slower6.98 us: 1.02x slower
lines: 34 raw_text: " "7.27 us7.51 us: 1.03x slower7.38 us: 1.01x slower
lines: 36 raw_text: " "7.71 us7.86 us: 1.02x slower7.81 us: 1.01x slower
lines: 2 raw_text: "\t"1.07 us833 ns: 1.28x faster842 ns: 1.27x faster
lines: 4 raw_text: "\t"1.37 us1.28 us: 1.07x faster1.28 us: 1.07x faster
lines: 6 raw_text: "\t"1.69 us1.60 us: 1.06x faster1.59 us: 1.07x faster
lines: 8 raw_text: "\t"1.99 us1.89 us: 1.06x faster1.92 us: 1.04x faster
lines: 10 raw_text: "\t"2.28 us2.24 us: 1.02x faster2.24 us: 1.02x faster
lines: 14 raw_text: "\t"3.04 usnot significant2.95 us: 1.03x faster
lines: 20 raw_text: "\t"4.10 us4.21 us: 1.03x slower4.03 us: 1.02x faster
lines: 22 raw_text: "\t"4.52 us4.58 us: 1.01x slowernot significant
lines: 24 raw_text: "\t"4.95 us5.03 us: 1.02x slowernot significant
lines: 28 raw_text: "\t"5.85 us5.96 us: 1.02x slowernot significant
lines: 34 raw_text: "\t"7.02 us7.30 us: 1.04x slower7.16 us: 1.02x slower
lines: 36 raw_text: "\t"7.43 us7.65 us: 1.03x slower7.50 us: 1.01x slower
lines: 38 raw_text: "\t"7.80 us8.02 us: 1.03x slower8.01 us: 1.03x slower
lines: 40 raw_text: "\t"8.09 us8.32 us: 1.03x slowernot significant
lines: 42 raw_text: "\t"8.49 us8.78 us: 1.03x slowernot significant
lines: 44 raw_text: "\t"8.91 us9.31 us: 1.04x slower9.16 us: 1.03x slower
lines: 46 raw_text: "\t"9.36 us9.63 us: 1.03x slowernot significant
lines: 48 raw_text: "\t"9.75 us10.0 us: 1.03x slower9.94 us: 1.02x slower
lines: 2 raw_text: " \t abc"1.14 us993 ns: 1.15x faster1.00 us: 1.13x faster
lines: 4 raw_text: " \t abc"1.57 us1.47 us: 1.07x faster1.47 us: 1.07x faster
lines: 6 raw_text: " \t abc"1.90 us1.79 us: 1.06x faster1.80 us: 1.05x faster
lines: 8 raw_text: " \t abc"2.22 us2.09 us: 1.06x faster2.10 us: 1.06x faster
lines: 10 raw_text: " \t abc"2.51 us2.43 us: 1.03x faster2.46 us: 1.02x faster
lines: 12 raw_text: " \t abc"2.96 us2.89 us: 1.02x faster2.89 us: 1.02x faster
lines: 14 raw_text: " \t abc"3.39 us3.27 us: 1.04x faster3.23 us: 1.05x faster
lines: 18 raw_text: " \t abc"4.07 usnot significant4.00 us: 1.02x faster
lines: 20 raw_text: " \t abc"4.44 us4.36 us: 1.02x fasternot significant
lines: 24 raw_text: " \t abc"5.30 us5.38 us: 1.01x slowernot significant
lines: 30 raw_text: " \t abc"6.47 us6.53 us: 1.01x slowernot significant
lines: 38 raw_text: " \t abc"8.15 us8.33 us: 1.02x slower8.37 us: 1.03x slower
lines: 40 raw_text: " \t abc"8.46 us8.58 us: 1.01x slower8.72 us: 1.03x slower
lines: 42 raw_text: " \t abc"8.88 us9.10 us: 1.02x slowernot significant
lines: 44 raw_text: " \t abc"9.26 us9.46 us: 1.02x slower9.49 us: 1.02x slower
lines: 46 raw_text: " \t abc"9.73 us9.91 us: 1.02x slower10.0 us: 1.03x slower
lines: 48 raw_text: " \t abc"10.2 us10.4 us: 1.03x slower10.4 us: 1.03x slower
lines: 2 raw_text: " \t abc \t "1.15 us997 ns: 1.16x faster1.01 us: 1.14x faster
lines: 4 raw_text: " \t abc \t "1.56 us1.48 us: 1.06x faster1.49 us: 1.05x faster
lines: 6 raw_text: " \t abc \t "1.90 us1.80 us: 1.06x faster1.83 us: 1.04x faster
lines: 8 raw_text: " \t abc \t "2.27 us2.16 us: 1.05x faster2.17 us: 1.05x faster
lines: 10 raw_text: " \t abc \t "2.57 us2.46 us: 1.05x faster2.50 us: 1.03x faster
lines: 12 raw_text: " \t abc \t "3.01 us2.94 us: 1.02x faster2.95 us: 1.02x faster
lines: 14 raw_text: " \t abc \t "3.37 us3.28 us: 1.03x faster3.24 us: 1.04x faster
lines: 22 raw_text: " \t abc \t "4.83 us4.97 us: 1.03x slower4.90 us: 1.02x slower
lines: 26 raw_text: " \t abc \t "5.82 us5.93 us: 1.02x slower5.89 us: 1.01x slower
lines: 30 raw_text: " \t abc \t "6.50 us6.67 us: 1.03x slower6.62 us: 1.02x slower
lines: 34 raw_text: " \t abc \t "7.48 usnot significant7.62 us: 1.02x slower
lines: 36 raw_text: " \t abc \t "7.89 us8.04 us: 1.02x slower8.01 us: 1.02x slower
lines: 42 raw_text: " \t abc \t "8.94 us9.13 us: 1.02x slower9.27 us: 1.04x slower
lines: 44 raw_text: " \t abc \t "9.47 us9.64 us: 1.02x slower9.64 us: 1.02x slower
lines: 46 raw_text: " \t abc \t "9.87 us10.1 us: 1.02x slower10.1 us: 1.02x slower
lines: 48 raw_text: " \t abc \t "10.3 us10.6 us: 1.03x slower10.5 us: 1.03x slower
lines: 2 raw_text: 1000 spaces59.4 us58.5 us: 1.02x faster60.8 us: 1.02x slower
lines: 4 raw_text: 1000 spaces63.1 us62.0 us: 1.02x faster64.7 us: 1.03x slower
lines: 6 raw_text: 1000 spaces66.2 us63.3 us: 1.05x fasternot significant
lines: 8 raw_text: 1000 spaces66.8 us64.5 us: 1.04x fasternot significant
lines: 10 raw_text: 1000 spaces68.9 us65.4 us: 1.05x fasternot significant
lines: 12 raw_text: 1000 spaces73.1 us68.7 us: 1.06x faster71.5 us: 1.02x faster
lines: 14 raw_text: 1000 spaces74.9 us70.3 us: 1.06x faster73.6 us: 1.02x faster
lines: 16 raw_text: 1000 spaces77.4 us71.8 us: 1.08x faster74.2 us: 1.04x faster
lines: 18 raw_text: 1000 spaces80.8 us73.9 us: 1.09x faster77.5 us: 1.04x faster
lines: 20 raw_text: 1000 spaces83.1 us76.1 us: 1.09x faster78.9 us: 1.05x faster
lines: 22 raw_text: 1000 spaces86.4 us79.2 us: 1.09x faster82.0 us: 1.05x faster
lines: 24 raw_text: 1000 spaces90.6 us82.8 us: 1.09x faster84.0 us: 1.08x faster
lines: 26 raw_text: 1000 spaces94.1 us83.8 us: 1.12x faster86.8 us: 1.08x faster
lines: 28 raw_text: 1000 spaces98.3 us86.5 us: 1.14x faster89.0 us: 1.10x faster
lines: 30 raw_text: 1000 spaces100 us88.1 us: 1.14x faster90.5 us: 1.11x faster
lines: 32 raw_text: 1000 spaces104 us90.3 us: 1.15x faster93.0 us: 1.11x faster
lines: 34 raw_text: 1000 spaces108 us93.3 us: 1.16x faster95.9 us: 1.13x faster
lines: 36 raw_text: 1000 spaces111 us96.1 us: 1.15x faster98.5 us: 1.12x faster
lines: 38 raw_text: 1000 spaces112 us98.4 us: 1.14x faster99.6 us: 1.13x faster
lines: 40 raw_text: 1000 spaces117 us99.3 us: 1.17x faster101 us: 1.15x faster
lines: 42 raw_text: 1000 spaces124 us102 us: 1.21x faster105 us: 1.18x faster
lines: 44 raw_text: 1000 spaces129 us106 us: 1.21x faster107 us: 1.21x faster
lines: 46 raw_text: 1000 spaces134 us108 us: 1.25x faster110 us: 1.22x faster
lines: 48 raw_text: 1000 spaces134 us111 us: 1.21x faster113 us: 1.19x faster
Geometric mean(ref)1.02x faster1.02x faster

Large file

Benchmarkraw_scalenew_scalenew2_scale
lines: 500 raw_text: no prefix93.0 us99.2 us: 1.07x slowernot significant
lines: 1000 raw_text: no prefix193 us203 us: 1.05x slower188 us: 1.03x faster
lines: 1500 raw_text: no prefix289 us306 us: 1.06x slowernot significant
lines: 2000 raw_text: no prefix387 us415 us: 1.07x slowernot significant
lines: 2500 raw_text: no prefix493 us521 us: 1.06x slowernot significant
lines: 3000 raw_text: no prefix593 us639 us: 1.08x slowernot significant
lines: 3500 raw_text: no prefix697 us738 us: 1.06x slowernot significant
lines: 4000 raw_text: no prefix799 us841 us: 1.05x slowernot significant
lines: 4500 raw_text: no prefix895 us952 us: 1.06x slowernot significant
lines: 5000 raw_text: no prefix1.01 ms1.07 ms: 1.06x slowernot significant
lines: 5500 raw_text: no prefix1.10 ms1.18 ms: 1.07x slowernot significant
lines: 6000 raw_text: no prefix1.21 ms1.29 ms: 1.07x slowernot significant
lines: 6500 raw_text: no prefix1.31 ms1.39 ms: 1.06x slowernot significant
lines: 7000 raw_text: no prefix1.43 ms1.52 ms: 1.07x slowernot significant
lines: 7500 raw_text: no prefix1.52 ms1.61 ms: 1.06x slowernot significant
lines: 8000 raw_text: no prefix1.63 ms1.73 ms: 1.06x slowernot significant
lines: 8500 raw_text: no prefix1.71 ms1.81 ms: 1.06x slowernot significant
lines: 9000 raw_text: no prefix1.82 ms1.92 ms: 1.05x slowernot significant
lines: 9500 raw_text: no prefix1.92 ms2.04 ms: 1.06x slowernot significant
lines: 500 raw_text: "abc \t"89.7 us99.2 us: 1.11x slowernot significant
lines: 1000 raw_text: "abc \t"175 us201 us: 1.15x slowernot significant
lines: 1500 raw_text: "abc \t"265 us300 us: 1.13x slowernot significant
lines: 2000 raw_text: "abc \t"354 us404 us: 1.14x slowernot significant
lines: 2500 raw_text: "abc \t"446 us523 us: 1.17x slowernot significant
lines: 3000 raw_text: "abc \t"537 us609 us: 1.14x slowernot significant
lines: 3500 raw_text: "abc \t"628 us708 us: 1.13x slowernot significant
lines: 4000 raw_text: "abc \t"718 us813 us: 1.13x slowernot significant
lines: 4500 raw_text: "abc \t"803 us920 us: 1.15x slowernot significant
lines: 5000 raw_text: "abc \t"908 us1.02 ms: 1.13x slowernot significant
lines: 5500 raw_text: "abc \t"988 us1.13 ms: 1.14x slower1.02 ms: 1.03x slower
lines: 6000 raw_text: "abc \t"1.09 ms1.26 ms: 1.16x slowernot significant
lines: 6500 raw_text: "abc \t"1.18 ms1.33 ms: 1.13x slowernot significant
lines: 7000 raw_text: "abc \t"1.28 ms1.44 ms: 1.12x slowernot significant
lines: 7500 raw_text: "abc \t"1.37 ms1.54 ms: 1.13x slowernot significant
lines: 8000 raw_text: "abc \t"1.47 ms1.63 ms: 1.11x slowernot significant
lines: 8500 raw_text: "abc \t"1.54 ms1.75 ms: 1.14x slowernot significant
lines: 9000 raw_text: "abc \t"1.64 ms1.88 ms: 1.15x slowernot significant
lines: 9500 raw_text: "abc \t"1.72 ms1.93 ms: 1.12x slowernot significant
lines: 500 raw_text: " "104 us108 us: 1.04x slowernot significant
lines: 1000 raw_text: " "213 us221 us: 1.04x slowernot significant
lines: 1500 raw_text: " "320 us336 us: 1.05x slowernot significant
lines: 2000 raw_text: " "435 us473 us: 1.09x slowernot significant
lines: 2500 raw_text: " "544 us563 us: 1.04x slowernot significant
lines: 3000 raw_text: " "658 us684 us: 1.04x slowernot significant
lines: 3500 raw_text: " "767 us798 us: 1.04x slowernot significant
lines: 4000 raw_text: " "884 us916 us: 1.04x slowernot significant
lines: 4500 raw_text: " "995 us1.05 ms: 1.05x slower1.02 ms: 1.03x slower
lines: 5000 raw_text: " "1.11 ms1.22 ms: 1.10x slowernot significant
lines: 5500 raw_text: " "1.22 ms1.28 ms: 1.05x slower1.21 ms: 1.01x faster
lines: 6000 raw_text: " "1.34 ms1.40 ms: 1.04x slowernot significant
lines: 6500 raw_text: " "1.46 ms1.51 ms: 1.04x slowernot significant
lines: 7000 raw_text: " "1.57 ms1.63 ms: 1.04x slower1.60 ms: 1.02x slower
lines: 7500 raw_text: " "1.68 ms1.74 ms: 1.04x slowernot significant
lines: 8000 raw_text: " "1.79 ms1.86 ms: 1.04x slowernot significant
lines: 8500 raw_text: " "1.93 ms1.98 ms: 1.03x slowernot significant
lines: 9000 raw_text: " "2.02 ms2.08 ms: 1.03x slowernot significant
lines: 9500 raw_text: " "2.12 ms2.21 ms: 1.04x slowernot significant
lines: 500 raw_text: "\t"101 us106 us: 1.05x slowernot significant
lines: 1000 raw_text: "\t"206 us217 us: 1.05x slowernot significant
lines: 1500 raw_text: "\t"318 us331 us: 1.04x slowernot significant
lines: 2000 raw_text: "\t"427 us443 us: 1.04x slower421 us: 1.01x faster
lines: 2500 raw_text: "\t"537 us569 us: 1.06x slowernot significant
lines: 3000 raw_text: "\t"644 us677 us: 1.05x slowernot significant
lines: 3500 raw_text: "\t"758 us790 us: 1.04x slowernot significant
lines: 4000 raw_text: "\t"866 us908 us: 1.05x slowernot significant
lines: 4500 raw_text: "\t"981 us1.03 ms: 1.05x slowernot significant
lines: 5000 raw_text: "\t"1.10 ms1.15 ms: 1.05x slowernot significant
lines: 5500 raw_text: "\t"1.20 ms1.26 ms: 1.05x slowernot significant
lines: 6000 raw_text: "\t"1.32 ms1.38 ms: 1.04x slowernot significant
lines: 6500 raw_text: "\t"1.43 ms1.50 ms: 1.06x slowernot significant
lines: 7000 raw_text: "\t"1.55 ms1.62 ms: 1.05x slowernot significant
lines: 7500 raw_text: "\t"1.66 ms1.72 ms: 1.04x slowernot significant
lines: 8000 raw_text: "\t"1.79 ms1.84 ms: 1.03x slowernot significant
lines: 8500 raw_text: "\t"1.91 ms1.97 ms: 1.03x slowernot significant
lines: 9000 raw_text: "\t"1.98 ms2.07 ms: 1.04x slowernot significant
lines: 9500 raw_text: "\t"2.10 ms2.19 ms: 1.04x slowernot significant
lines: 500 raw_text: " \t abc"101 us106 us: 1.05x slower99.5 us: 1.01x faster
lines: 1000 raw_text: " \t abc"198 us214 us: 1.08x slowernot significant
lines: 1500 raw_text: " \t abc"299 us323 us: 1.08x slowernot significant
lines: 2000 raw_text: " \t abc"404 us436 us: 1.08x slowernot significant
lines: 2500 raw_text: " \t abc"500 us553 us: 1.11x slowernot significant
lines: 3000 raw_text: " \t abc"611 us658 us: 1.08x slowernot significant
lines: 3500 raw_text: " \t abc"703 us778 us: 1.11x slowernot significant
lines: 4000 raw_text: " \t abc"806 us880 us: 1.09x slowernot significant
lines: 4500 raw_text: " \t abc"916 us1.01 ms: 1.10x slowernot significant
lines: 5000 raw_text: " \t abc"1.01 ms1.12 ms: 1.10x slowernot significant
lines: 5500 raw_text: " \t abc"1.12 ms1.23 ms: 1.10x slowernot significant
lines: 6000 raw_text: " \t abc"1.22 ms1.35 ms: 1.10x slowernot significant
lines: 6500 raw_text: " \t abc"1.33 ms1.47 ms: 1.11x slowernot significant
lines: 7000 raw_text: " \t abc"1.43 ms1.56 ms: 1.09x slowernot significant
lines: 7500 raw_text: " \t abc"1.52 ms1.67 ms: 1.10x slower1.54 ms: 1.02x slower
lines: 8000 raw_text: " \t abc"1.64 ms1.77 ms: 1.08x slowernot significant
lines: 8500 raw_text: " \t abc"1.72 ms1.88 ms: 1.10x slower1.74 ms: 1.01x slower
lines: 9000 raw_text: " \t abc"1.83 ms2.00 ms: 1.09x slower1.82 ms: 1.01x faster
lines: 9500 raw_text: " \t abc"2.28 ms2.49 ms: 1.09x slowernot significant
lines: 500 raw_text: " \t abc \t "102 us115 us: 1.13x slowernot significant
lines: 1000 raw_text: " \t abc \t "199 us228 us: 1.15x slower203 us: 1.02x slower
lines: 1500 raw_text: " \t abc \t "303 us326 us: 1.07x slowernot significant
lines: 2000 raw_text: " \t abc \t "400 us438 us: 1.09x slowernot significant
lines: 2500 raw_text: " \t abc \t "504 us549 us: 1.09x slowernot significant
lines: 3000 raw_text: " \t abc \t "611 us659 us: 1.08x slowernot significant
lines: 3500 raw_text: " \t abc \t "715 us768 us: 1.07x slowernot significant
lines: 4000 raw_text: " \t abc \t "816 us884 us: 1.08x slowernot significant
lines: 4500 raw_text: " \t abc \t "912 us1.01 ms: 1.10x slowernot significant
lines: 5000 raw_text: " \t abc \t "1.03 ms1.12 ms: 1.09x slowernot significant
lines: 5500 raw_text: " \t abc \t "1.13 ms1.24 ms: 1.10x slowernot significant
lines: 6000 raw_text: " \t abc \t "1.23 ms1.35 ms: 1.09x slowernot significant
lines: 6500 raw_text: " \t abc \t "1.33 ms1.45 ms: 1.09x slowernot significant
lines: 7000 raw_text: " \t abc \t "1.44 ms1.56 ms: 1.08x slowernot significant
lines: 7500 raw_text: " \t abc \t "1.54 ms1.67 ms: 1.08x slowernot significant
lines: 8000 raw_text: " \t abc \t "1.64 ms1.78 ms: 1.09x slowernot significant
lines: 8500 raw_text: " \t abc \t "1.75 ms1.91 ms: 1.09x slowernot significant
lines: 9000 raw_text: " \t abc \t "2.19 ms2.30 ms: 1.05x slowernot significant
lines: 9500 raw_text: " \t abc \t "2.33 ms2.53 ms: 1.08x slowernot significant
lines: 500 raw_text: 1000 spaces906 us680 us: 1.33x faster928 us: 1.02x slower
lines: 1000 raw_text: 1000 spaces1.79 ms1.31 ms: 1.36x fasternot significant
lines: 1500 raw_text: 1000 spaces2.67 ms1.95 ms: 1.37x fasternot significant
lines: 2000 raw_text: 1000 spaces3.55 ms2.62 ms: 1.36x fasternot significant
lines: 2500 raw_text: 1000 spaces4.42 ms3.25 ms: 1.36x fasternot significant
lines: 3000 raw_text: 1000 spaces5.63 ms3.88 ms: 1.45x faster5.72 ms: 1.02x slower
lines: 3500 raw_text: 1000 spaces6.67 ms4.51 ms: 1.48x faster6.87 ms: 1.03x slower
lines: 4000 raw_text: 1000 spaces7.73 ms5.60 ms: 1.38x faster7.85 ms: 1.02x slower
lines: 4500 raw_text: 1000 spaces8.83 ms6.46 ms: 1.37x fasternot significant
lines: 5000 raw_text: 1000 spaces9.91 ms7.28 ms: 1.36x fasternot significant
lines: 5500 raw_text: 1000 spaces11.0 ms8.12 ms: 1.35x fasternot significant
lines: 6000 raw_text: 1000 spaces12.0 ms9.02 ms: 1.34x faster12.2 ms: 1.02x slower
lines: 6500 raw_text: 1000 spaces13.1 ms9.76 ms: 1.34x faster13.2 ms: 1.01x slower
lines: 7000 raw_text: 1000 spaces14.2 ms10.7 ms: 1.33x faster14.3 ms: 1.01x slower
lines: 7500 raw_text: 1000 spaces15.5 ms11.5 ms: 1.35x faster15.3 ms: 1.01x faster
lines: 8000 raw_text: 1000 spaces16.5 ms12.3 ms: 1.34x fasternot significant
lines: 8500 raw_text: 1000 spaces17.6 ms13.4 ms: 1.31x fasternot significant
lines: 9000 raw_text: 1000 spaces18.8 ms14.1 ms: 1.33x fasternot significant
lines: 9500 raw_text: 1000 spaces20.0 ms15.0 ms: 1.33x fasternot significant
Geometric mean(ref)1.02x slower1.00x slower

So on the large files we get 0 improvement, a 13% slight improvement on the synthetic test benches and on smaller values

@Marius-Juston
Copy link
ContributorAuthor

I'm against this change not only because it's harder to read but also because it only offers an overall <10% speed-up. In general, we accept optimizations exceeding that threshold.

Agreed that this optimization is most likely not necessary, though this is very slightly more efficient memory wise since it does not have a non_blank_lines variable so it technically only duplicates the lines variable only twice rather than 3 times like in the current implementation ( in real world this is most definitively not really a problem just a thought )

Comment on lines +435 to +453
val = False
for i, line in enumerate(lines):
# Compute min + max concurrently + normalize others
if line and not line.isspace():
if val:
if line < l1:
l1 = line
elif line > l2:
l2 = line
else:
val = True
l1 = l2 = line

else:
lines[i] = ''

if not val or not l1:
return '\n'.join(lines)

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
val=False
fori, lineinenumerate(lines):
# Compute min + max concurrently + normalize others
iflineandnotline.isspace():
ifval:
ifline<l1:
l1=line
elifline>l2:
l2=line
else:
val=True
l1=l2=line
else:
lines[i] =''
ifnotvalornotl1:
return'\n'.join(lines)
l1='z'
l2=''
fori, lineinenumerate(lines):
# Compute min + max concurrently + normalize others
iflineandnotline.isspace():
ifline<l1:
l1=line
ifline>l2:
l2=line
else:
lines[i] =''
ifnotl1:
return'\n'.join(lines)
margin=0
formargin, cinenumerate(l2):
ifc!=l1[margin] orcnotin' \t':
break

This saves chechking the val. Performance gain is only a bit though.

I agree with the other reviewers: unless we find out a way to make this much faster, the small gains are not worth the change.

@Marius-Juston Thanks for putting in the work to get all the performance numbers!

@picnixzpicnixz added the pending The issue will be closed if no feedback is provided label Mar 31, 2025
Copy link
Member

@ZeroIntensityZeroIntensity left a comment

Choose a reason for hiding this comment

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

Thanks for getting the benchmarks, sometimes its hard to get contributors to quote numbers, and you've gone above and beyond with benchmarking :).

But unfortunately, the numbers make me -1 on this.

  • min/max are builtins that are written in C; they're pretty fast, especially compared to multiple lines of Python code. If we're concerned about those being slow, let's try to optimize those on the C level instead.
  • There is a significant amount of added complexity here, for seemingly not much benefit.
  • Optimizing Python code by shifting things around is generally not a good idea, because when the interpreter changes, those optimizations become obsolete. We should definitely not be quoting memory usage, number of (pointer) copies, or number of lookups; those are all things that change on an interpreter-wide level.

I've learned that it can be hard to know when to stop painting. I think we should put down the brush, and enjoy the optimization that's already landed 🙂.

@Marius-Juston
Copy link
ContributorAuthor

Makes sense. I am just having so much fun doing this it is definitely hard to stop lol!

@Marius-Juston
Copy link
ContributorAuthor

Closing this down then! ( I will be putting a feature request for the min_max implementation)

@picnixz
Copy link
Member

picnixz commented Mar 31, 2025

I will be putting a feature request for the min_max implementation

I think it's already been proposed but rejected so search through issues and https://discuss.python.org/c/ideas/6 first.

@Marius-Juston
Copy link
ContributorAuthor

I think it's already been proposed but rejected so search through issues and https://discuss.python.org/c/ideas/6 first.

I think I found it, the https://discuss.python.org/t/minmax-function-alongside-min-and-max/2834/73 issue got closed down. It seems like it got stale and just ignored? A shame.

@AA-Turner
Copy link
Member

Feel free to open a new thread referencing the one you found. Personally I'd suggest statistics.min_max. It might be useful to identify a few motivating examples in the stdlib / popular packages -- this will be one of the first questions you're asked on Discourse.

A

@AA-TurnerAA-Turner removed the pending The issue will be closed if no feedback is provided label Apr 6, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@Marius-Juston@AA-Turner@picnixz@eendebakpt@ZeroIntensity