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

FindSubstring<&[u8]>: make use of memchr::memmem #1375

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

homersimpsons
Copy link
Contributor

@homersimpsons homersimpsons commented Aug 27, 2021

I guess that #565 could be closed with this one.

memchr MSRV is rust 1.41.1 so it should be okay.

FTR I did run criterion before and after the change

Gnuplot not found, using plotters backend
arithmetic              time:   [324.31 ns 326.60 ns 329.47 ns]                       
                        change: [-10.858% -8.9005% -6.6184%] (p = 0.00 < 0.05)
                        Performance has improved.

Gnuplot not found, using plotters backend
http/parse/291          time:   [549.57 ns 553.83 ns 559.13 ns]                            
                        thrpt:  [496.34 MiB/s 501.09 MiB/s 504.97 MiB/s]
                 change:
                        time:   [-3.8074% +0.3270% +4.5768%] (p = 0.89 > 0.05)
                        thrpt:  [-4.3765% -0.3259% +3.9581%]
                        No change in performance detected.

Gnuplot not found, using plotters backend
ini/parse/110           time:   [787.46 ns 792.56 ns 798.07 ns]                           
                        thrpt:  [131.45 MiB/s 132.36 MiB/s 133.22 MiB/s]
                 change:
                        time:   [+22.871% +26.582% +29.885%] (p = 0.00 < 0.05)
                        thrpt:  [-23.009% -21.000% -18.614%]
                        Performance has regressed.

ini keys and values/parse/45                                                                            
                        time:   [71.192 ns 71.775 ns 72.519 ns]
                        thrpt:  [591.78 MiB/s 597.92 MiB/s 602.81 MiB/s]
                 change:
                        time:   [-0.5977% +1.4548% +3.3841%] (p = 0.15 > 0.05)
                        thrpt:  [-3.2733% -1.4340% +0.6013%]
                        No change in performance detected.

ini key value/parse/18  time:   [42.604 ns 42.760 ns 42.921 ns]                                    
                        thrpt:  [399.95 MiB/s 401.45 MiB/s 402.92 MiB/s]
                 change:
                        time:   [-0.8172% +1.9369% +5.2980%] (p = 0.22 > 0.05)
                        thrpt:  [-5.0314% -1.9001% +0.8239%]
                        No change in performance detected.

Gnuplot not found, using plotters backend
ini str/parse/109       time:   [600.73 ns 603.32 ns 606.57 ns]                               
                        thrpt:  [171.37 MiB/s 172.30 MiB/s 173.04 MiB/s]
                 change:
                        time:   [-2.5620% -0.3528% +1.6800%] (p = 0.76 > 0.05)
                        thrpt:  [-1.6523% +0.3541% +2.6294%]
                        No change in performance detected.

Gnuplot not found, using plotters backend
json                    time:   [1.4783 us 1.4887 us 1.5011 us]                  
                        change: [-2.8551% -0.7999% +1.1989%] (p = 0.46 > 0.05)
                        No change in performance detected.

recognize_float_bytes result: Ok(([], [45, 49, 46, 50, 51, 52, 69, 45, 49, 50]))
recognize float bytes   time:   [2.8242 ns 2.8338 ns 2.8450 ns]                                   
                        change: [-1.3723% +0.5253% +2.3393%] (p = 0.60 > 0.05)
                        No change in performance detected.

recognize_float_str result: Ok(("", "-1.234E-12"))
recognize float str     time:   [31.359 ns 31.962 ns 32.774 ns]                                 
                        change: [+12.350% +20.029% +27.497%] (p = 0.00 < 0.05)
                        Performance has regressed.

float_bytes result: Ok(([], -0.000000000001234))
float bytes             time:   [14.015 ns 14.120 ns 14.236 ns]                         
                        change: [-3.7928% -1.5161% +0.7351%] (p = 0.21 > 0.05)
                        No change in performance detected.

std_float_bytes result: Ok(([], -0.000000000001234))
std_float bytes         time:   [43.579 ns 43.740 ns 43.924 ns]                             
                        change: [-2.2323% -0.1400% +2.2061%] (p = 0.90 > 0.05)
                        No change in performance detected.

float_str result: Ok(("", -0.000000000001234))
float str               time:   [15.227 ns 15.304 ns 15.394 ns]                       
                        change: [-2.2072% +0.1313% +2.3043%] (p = 0.91 > 0.05)
                        No change in performance detected.

Gnuplot not found, using plotters backend
number                  time:   [1.0228 ns 1.0317 ns 1.0397 ns]                    
                        change: [+9.4588% +10.853% +12.215%] (p = 0.00 < 0.05)
                        Performance has regressed.

@homersimpsons homersimpsons force-pushed the feature/memmem branch 2 times, most recently from a33987b to 129ce0a Compare October 25, 2021 08:04
@homersimpsons
Copy link
Contributor Author

homersimpsons commented Oct 25, 2021

Note: I just force-pushed to retry CI, I could not rerun as "[the] workflow file may be broken."

@coveralls
Copy link

coveralls commented Oct 25, 2021

Coverage Status

Coverage decreased (-2.8%) to 81.145% when pulling 3de6704 on homersimpsons:feature/memmem into 4a2f9af on Geal:master.

@Geal
Copy link
Collaborator

Geal commented Oct 25, 2021

At this point I'm wondering if using memchr is still the right approach, considering that a lot of parsers looking for a specific token or substring work on very small inputs. Maybe we should compare with a naive implementation

@epage
Copy link
Contributor

epage commented Aug 17, 2023

My findings are

  • memchr is worth it on an opt-in basis
  • memmem is not worth it

winnow took the approach of putting memchr behind a simd feature flag and merged this PR in winnow-rs/winnow#86. For every case I've dealt with until now, the simd feature flag was not needed.

Recently, I've been working with Byron on porting gitoxide from nom to winnow (GitoxideLabs/gitoxide#956). Within gitoxide, the use of memchr improves performance by an order of magnitude (from 1.6198 µs to 239.23 ns). Removing memmem further improved performance (no official numbers yet, but more around 170ns)

@epage
Copy link
Contributor

epage commented Aug 17, 2023

Important to note that for gitoxide, take_until looks for

  • space
  • newline
  • :
  • >
  • <
  • PGP signature begin
  • PGP signature end

So its a mix of single-character (the memchr shortcut) and actual substring search

@Geal
Copy link
Collaborator

Geal commented Aug 17, 2023

substring search and single character matching could work better as different combinators, they are not meant for the same task, and usually don't happen on the same amount of data. Thank you for taking the time to measure this on a larger codebase

@homersimpsons homersimpsons requested a review from Geal as a code owner May 5, 2024 16:33
Copy link

codecov bot commented May 5, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 61.47%. Comparing base (83cfb17) to head (8a9579a).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1375   +/-   ##
=======================================
  Coverage   61.47%   61.47%           
=======================================
  Files          24       24           
  Lines        2951     2936   -15     
=======================================
- Hits         1814     1805    -9     
+ Misses       1137     1131    -6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

codspeed-hq bot commented May 5, 2024

CodSpeed Performance Report

Merging #1375 will not alter performance

Comparing homersimpsons:feature/memmem (8a9579a) with main (83cfb17)

Summary

✅ 24 untouched benchmarks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants