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

String#=~ faster than String#match #59

Merged

Conversation

@schneems
Copy link
Contributor

commented Aug 6, 2015

If you're only looking for presence of a match and don't need the matchdata, use String#=~

schneems/rails@1bf50ba#commitcomment-12572839

String#=~ faster than String#match
If you're only looking for presence of a match and don't need the matchdata, use String#=~ 

schneems/rails@1bf50ba#commitcomment-12572839

schneems referenced this pull request in schneems/rails Aug 6, 2015

Decrease string allocations in apply_inflections
In `apply_inflections` a string is down cased and some whitespace stripped in the front (which allocate strings). This would normally be fine, however `uncountables` is a fairly small array (10 elements out of the box) and this method gets called a TON. Instead we can keep an array of valid regexes for each uncountable so we don't have to allocate new strings.

This change buys us 325,106 bytes of memory and 3,251 fewer objects per request.
@Arcovion

This comment has been minimized.

Copy link
Collaborator

commented Aug 6, 2015

Regexp#=== is a tiny bit faster on my machine, worth including:

require 'benchmark/ips'

def fastest
  /boo/ === 'foo'.freeze
end

def fast
  'foo'.freeze =~ /boo/
end

def slow
  'foo'.freeze.match(/boo/)
end

Benchmark.ips do |bm|
  bm.report("Regexp#===") { fastest }
  bm.report("String#=~") { fast }
  bm.report("String#match") { slow }
  bm.compare!
end
Calculating -------------------------------------
          Regexp#===   116.319k i/100ms
           String#=~   119.576k i/100ms
        String#match   102.506k i/100ms
-------------------------------------------------
          Regexp#===      3.048M (± 1.5%) i/s -     15.238M
           String#=~      2.988M (± 1.4%) i/s -     14.947M
        String#match      2.482M (± 1.2%) i/s -     12.506M

Comparison:
          Regexp#===:  3047884.6 i/s
           String#=~:  2988148.2 i/s - 1.02x slower
        String#match:  2481615.6 i/s - 1.23x slower
@schneems

This comment has been minimized.

Copy link
Contributor Author

commented Aug 6, 2015

Yep

Calculating -------------------------------------
           String#=~    66.023k i/100ms
        String#match    60.124k i/100ms
          String#===    70.747k i/100ms
-------------------------------------------------
           String#=~      1.798M (±10.3%) i/s -      8.913M
        String#match      1.374M (± 9.7%) i/s -      6.854M
          String#===      1.847M (± 9.8%) i/s -      9.197M

Seems good. How should I report this? I would like to have all 3 examples in the code and reported.

@Arcovion

This comment has been minimized.

Copy link
Collaborator

commented Aug 6, 2015

Edited my comment as String#=== was wrong, I meant Regexp#===
Added example of how it might look...

@JuanitoFatas

This comment has been minimized.

Copy link
Owner

commented Aug 7, 2015

How about list all possibilities (code/string/===-vs-=~-vs-match.rb)?

require "benchmark/ips"

def fastest
  "foo".freeze === /boo/
end

def faster
  "foo".freeze =~ /boo/
end

def fast
  /boo/ === "foo".freeze
end

def slow
  "foo".freeze.match(/boo/)
end

Benchmark.ips do |x|
  x.report("String#===") { fastest }
  x.report("Regexp#===") { faster }
  x.report("String#=~") { fast }
  x.report("String#match") { slow }
  x.compare!
end
ruby -v code/string/match-vs-=\~.rb
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
Calculating -------------------------------------
          String#===   143.440k i/100ms
          Regexp#===    94.853k i/100ms
           String#=~    91.999k i/100ms
        String#match    88.397k i/100ms
-------------------------------------------------
          String#===      5.637M (± 7.4%) i/s -     28.114M
          Regexp#===      2.599M (± 5.4%) i/s -     12.995M
           String#=~      2.318M (± 7.7%) i/s -     11.592M
        String#match      1.905M (± 8.4%) i/s -      9.458M

Comparison:
          String#===:  5637360.8 i/s
          Regexp#===:  2599326.4 i/s - 2.17x slower
           String#=~:  2318149.8 i/s - 2.43x slower
        String#match:  1905484.8 i/s - 2.96x slower

@Arcovion

This comment has been minimized.

Copy link
Collaborator

commented Aug 7, 2015

String#=== doesn't work, it's not the correct result.

@JuanitoFatas

This comment has been minimized.

Copy link
Owner

commented Aug 7, 2015

String#=== doesn't work, it's not the correct result.

Yup. The #59 (comment) is wrong.

Let's keep this simple since the regexp need to flip the string to be compared to the end. Which is counterintuitive

JuanitoFatas added a commit that referenced this pull request Aug 7, 2015

Merge pull request #59 from schneems/schneems/string-equal-squigly
String#=~ faster than String#match

@JuanitoFatas JuanitoFatas merged commit df633ee into JuanitoFatas:master Aug 7, 2015

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

schneems added a commit to schneems/rails that referenced this pull request Aug 7, 2015

@schneems

This comment has been minimized.

Copy link
Contributor Author

commented Aug 7, 2015

It's a pretty big speed boost, we would have to rename it to Regexp#=== and we could put a warning in about not switching the arguments cause you'll get the wrong results

JuanitoFatas added a commit that referenced this pull request Nov 4, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.