Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize IOSource#read_until method by using StringScanner#check_until(string) #226

Merged
merged 1 commit into from
Dec 19, 2024

Conversation

naitoh
Copy link
Contributor

@naitoh naitoh commented Dec 15, 2024

Why?

StringScanner#check_until(string) is faster than StringScanner#check_until(regex).

See:

Benchmark

RUBYLIB= BUNDLER_ORIG_RUBYLIB= /Users/naitoh/.rbenv/versions/3.3.4/bin/ruby -v -S benchmark-driver /Users/naitoh/ghq/github.com/naitoh/rexml/benchmark/parse.yaml
ruby 3.3.4 (2024-07-09 revision be1089c8ec) [arm64-darwin22]
Calculating -------------------------------------
                         before       after  before(YJIT)  after(YJIT)
                 dom     19.459      19.840        35.035       35.786 i/s -     100.000 times in 5.139034s 5.040369s 2.854304s 2.794367s
                 sax     30.057      30.026        52.986       53.716 i/s -     100.000 times in 3.326998s 3.330499s 1.887303s 1.861652s
                pull     33.777      34.415        62.294       64.020 i/s -     100.000 times in 2.960622s 2.905668s 1.605284s 1.562002s
              stream     33.789      34.003        60.174       60.411 i/s -     100.000 times in 2.959521s 2.940916s 1.661845s 1.655334s

Comparison:
                              dom
         after(YJIT):        35.8 i/s
        before(YJIT):        35.0 i/s - 1.02x  slower
               after:        19.8 i/s - 1.80x  slower
              before:        19.5 i/s - 1.84x  slower

                              sax
         after(YJIT):        53.7 i/s
        before(YJIT):        53.0 i/s - 1.01x  slower
              before:        30.1 i/s - 1.79x  slower
               after:        30.0 i/s - 1.79x  slower

                             pull
         after(YJIT):        64.0 i/s
        before(YJIT):        62.3 i/s - 1.03x  slower
               after:        34.4 i/s - 1.86x  slower
              before:        33.8 i/s - 1.90x  slower

                           stream
         after(YJIT):        60.4 i/s
        before(YJIT):        60.2 i/s - 1.00x  slower
               after:        34.0 i/s - 1.78x  slower
              before:        33.8 i/s - 1.79x  slower

  • YJIT=ON : 1.00x - 1.03x faster
  • YJIT=OFF : 1.00x - 1.02x faster

## Why?
`StringScanner#check_until(string)` is faster than `StringScanner#check_until(regex)`.

## Benchmark
```
RUBYLIB= BUNDLER_ORIG_RUBYLIB= /Users/naitoh/.rbenv/versions/3.3.4/bin/ruby -v -S benchmark-driver /Users/naitoh/ghq/github.com/naitoh/rexml/benchmark/parse.yaml
ruby 3.3.4 (2024-07-09 revision be1089c8ec) [arm64-darwin22]
Calculating -------------------------------------
                         before       after  before(YJIT)  after(YJIT)
                 dom     19.459      19.840        35.035       35.786 i/s -     100.000 times in 5.139034s 5.040369s 2.854304s 2.794367s
                 sax     30.057      30.026        52.986       53.716 i/s -     100.000 times in 3.326998s 3.330499s 1.887303s 1.861652s
                pull     33.777      34.415        62.294       64.020 i/s -     100.000 times in 2.960622s 2.905668s 1.605284s 1.562002s
              stream     33.789      34.003        60.174       60.411 i/s -     100.000 times in 2.959521s 2.940916s 1.661845s 1.655334s

Comparison:
                              dom
         after(YJIT):        35.8 i/s
        before(YJIT):        35.0 i/s - 1.02x  slower
               after:        19.8 i/s - 1.80x  slower
              before:        19.5 i/s - 1.84x  slower

                              sax
         after(YJIT):        53.7 i/s
        before(YJIT):        53.0 i/s - 1.01x  slower
              before:        30.1 i/s - 1.79x  slower
               after:        30.0 i/s - 1.79x  slower

                             pull
         after(YJIT):        64.0 i/s
        before(YJIT):        62.3 i/s - 1.03x  slower
               after:        34.4 i/s - 1.86x  slower
              before:        33.8 i/s - 1.90x  slower

                           stream
         after(YJIT):        60.4 i/s
        before(YJIT):        60.2 i/s - 1.00x  slower
               after:        34.0 i/s - 1.78x  slower
              before:        33.8 i/s - 1.79x  slower

```

- YJIT=ON : 1.00x - 1.03x faster
- YJIT=OFF : 1.00x - 1.02x faster
@naitoh naitoh changed the title Optimize IOSource#read_until method Optimize IOSource#read_until method by using StringScanner#check_until(string) Dec 15, 2024
@naitoh naitoh marked this pull request as ready for review December 15, 2024 13:49
@naitoh naitoh requested a review from kou December 19, 2024 02:07
@kou kou merged commit bb0bedd into ruby:master Dec 19, 2024
61 checks passed
@kou
Copy link
Member

kou commented Dec 19, 2024

Thanks.

@naitoh naitoh deleted the use_check_until_string branch December 19, 2024 02:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants