Skip to content

Commit 7d52e31

Browse files
authored
Merge pull request #150 from bdewater/regexp-match-questionmark
Add `String#match?` to comparisons
2 parents 1b90498 + e951321 commit 7d52e31

File tree

4 files changed

+69
-49
lines changed

4 files changed

+69
-49
lines changed

README.md

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,11 @@ Comparison:
975975
String#+: 2977282.7 i/s - 1.80x slower
976976
```
977977

978-
##### `String#match` vs `String#start_with?`/`String#end_with?` [code (start)](code/string/start-string-checking-match-vs-start_with.rb) [code (end)](code/string/end-string-checking-match-vs-end_with.rb)
978+
##### `String#match` vs `String.match?` vs `String#start_with?`/`String#end_with?` [code (start)](code/string/start-string-checking-match-vs-start_with.rb) [code (end)](code/string/end-string-checking-match-vs-end_with.rb)
979+
980+
The regular expression approaches become slower as the tested string becomes
981+
longer. For short strings, `String#match?` performs similarly to
982+
`String#start_with?`/`String#end_with?`.
979983

980984
> :warning: <br>
981985
> Sometimes you cant replace regexp with `start_with?`, <br>
@@ -988,34 +992,32 @@ Comparison:
988992
989993
```
990994
$ ruby -v code/string/start-string-checking-match-vs-start_with.rb
991-
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
992-
993-
Calculating -------------------------------------
994-
String#=~ 56.672k i/100ms
995-
String#start_with? 118.308k i/100ms
996-
-------------------------------------------------
997-
String#=~ 919.574k (± 6.4%) i/s - 4.590M
998-
String#start_with? 4.177M (± 6.4%) i/s - 20.822M
995+
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-darwin17]
999996
1000-
Comparison:
1001-
String#start_with?: 4177162.6 i/s
1002-
String#=~: 919574.2 i/s - 4.54x slower
997+
Calculating -------------------------------------
998+
String#=~ 1.088M (± 4.0%) i/s - 5.471M in 5.034404s
999+
String#match? 5.138M (± 5.0%) i/s - 25.669M in 5.008810s
1000+
String#start_with? 6.314M (± 4.3%) i/s - 31.554M in 5.007207s
1001+
1002+
Comparison:
1003+
String#start_with?: 6314182.0 i/s
1004+
String#match?: 5138115.1 i/s - 1.23x slower
1005+
String#=~: 1088461.5 i/s - 5.80x slower
10031006
```
10041007

10051008
```
10061009
$ ruby -v code/string/end-string-checking-match-vs-end_with.rb
1007-
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
1010+
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-darwin17]
10081011
1009-
Calculating -------------------------------------
1010-
String#=~ 53.194k i/100ms
1011-
String#end_with? 105.871k i/100ms
1012-
-------------------------------------------------
1013-
String#=~ 891.124k (± 7.2%) i/s - 4.468M
1014-
String#end_with? 2.942M (± 7.6%) i/s - 14.610M
1015-
1016-
Comparison:
1017-
String#end_with?: 2942017.4 i/s
1018-
String#=~: 891124.1 i/s - 3.30x slower
1012+
Calculating -------------------------------------
1013+
String#=~ 918.101k (± 6.0%) i/s - 4.650M in 5.084079s
1014+
String#match? 3.009M (± 6.8%) i/s - 14.991M in 5.005691s
1015+
String#end_with? 4.548M (± 9.3%) i/s - 22.684M in 5.034115s
1016+
1017+
Comparison:
1018+
String#end_with?: 4547871.0 i/s
1019+
String#match?: 3008554.5 i/s - 1.51x slower
1020+
String#=~: 918100.5 i/s - 4.95x slower
10191021
```
10201022

10211023
##### `String#start_with?` vs `String#[].==` [code](code/string/start_with-vs-substring-==.rb)
@@ -1037,32 +1039,35 @@ Comparison:
10371039
String#[0...n] ==: 427206.8 i/s - 4.79x slower
10381040
```
10391041

1040-
##### `Regexp#===` vs `String#match` vs `String#=~` [code ](code/string/===-vs-=~-vs-match.rb)
1042+
##### `Regexp#===` vs `String#match` vs `String#=~` vs `String#match?` [code ](code/string/===-vs-=~-vs-match.rb)
1043+
1044+
`String#match?` and `Regexp#match?` are available on Ruby 2.4 or later.
1045+
ActiveSupport [provides](http://guides.rubyonrails.org/v5.1/active_support_core_extensions.html#match-questionmark)
1046+
a forward compatible extension of `Regexp` for older Rubies without the speed
1047+
improvement.
10411048

10421049
> :warning: <br>
1043-
> Sometimes you can't replace `match` with `=~`, <br>
1050+
> Sometimes you can't replace `match` with `match?`, <br>
10441051
> This is only useful for cases where you are checking <br>
10451052
> for a match and not using the resultant match object. <br>
10461053
> :warning: <br>
10471054
> `Regexp#===` is also faster than `String#match` but you need to switch the order of arguments.
10481055
10491056
```
1050-
$ ruby -v code/string/===-vs-=~-vs-match.rb.rb
1051-
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
1057+
$ ruby -v code/string/===-vs-=~-vs-match.rb
1058+
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-darwin17]
10521059
10531060
Calculating -------------------------------------
1054-
String#=~ 98.184k i/100ms
1055-
Regexp#=== 92.382k i/100ms
1056-
String#match 83.601k i/100ms
1057-
-------------------------------------------------
1058-
String#=~ 2.442M (± 7.6%) i/s - 12.175M
1059-
Regexp#=== 2.259M (± 7.9%) i/s - 11.271M
1060-
String#match 1.840M (± 7.3%) i/s - 9.196M
1061+
String#match? 6.284M (± 5.6%) i/s - 31.324M in 5.001471s
1062+
String#=~ 2.581M (± 4.7%) i/s - 12.977M in 5.038887s
1063+
Regexp#=== 2.482M (± 4.1%) i/s - 12.397M in 5.002808s
1064+
String#match 2.097M (± 4.3%) i/s - 10.592M in 5.060535s
10611065
10621066
Comparison:
1063-
String#=~: 2442335.1 i/s
1064-
Regexp#===: 2259277.3 i/s - 1.08x slower
1065-
String#match: 1839815.4 i/s - 1.33x slower
1067+
String#match?: 6283591.8 i/s
1068+
String#=~: 2581356.8 i/s - 2.43x slower
1069+
Regexp#===: 2482379.7 i/s - 2.53x slower
1070+
String#match: 2096984.3 i/s - 3.00x slower
10661071
```
10671072

10681073
See [#59](https://github.com/JuanitoFatas/fast-ruby/pull/59) and [#62](https://github.com/JuanitoFatas/fast-ruby/pull/62) for discussions.

code/string/===-vs-=~-vs-match.rb

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
require "benchmark/ips"
22

3-
def fastest
3+
def fast
4+
"foo".freeze.match?(/boo/)
5+
end
6+
7+
def slow
48
"foo".freeze =~ /boo/
59
end
610

7-
def fast
11+
def slower
812
/boo/ === "foo".freeze
913
end
1014

11-
def slow
15+
def slowest
1216
"foo".freeze.match(/boo/)
1317
end
1418

1519
Benchmark.ips do |x|
16-
x.report("String#=~") { fastest }
17-
x.report("Regexp#===") { fast }
18-
x.report("String#match") { slow }
20+
x.report("String#match?") { fast } if RUBY_VERSION >= "2.4.0".freeze
21+
x.report("String#=~") { slow }
22+
x.report("Regexp#===") { slower }
23+
x.report("String#match") { slowest }
1924
x.compare!
2025
end
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
require 'benchmark/ips'
22

3-
SLUG = 'root_url'
3+
SLUG = "some_kind_of_root_url"
44

5-
def slow
5+
def slower
66
SLUG =~ /_(path|url)$/
77
end
88

9+
def slow
10+
SLUG.match?(/_(path|url)$/)
11+
end
12+
913
def fast
1014
SLUG.end_with?('_path', '_url')
1115
end
1216

1317
Benchmark.ips do |x|
14-
x.report('String#=~') { slow }
18+
x.report('String#=~') { slower }
19+
x.report('String#match?') { slow } if RUBY_VERSION >= "2.4.0".freeze
1520
x.report('String#end_with?') { fast }
1621
x.compare!
1722
end
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
require 'benchmark/ips'
22

3-
SLUG = 'test_reverse_merge.rb'
3+
SLUG = 'test_some_kind_of_long_file_name.rb'
44

5-
def slow
5+
def slower
66
SLUG =~ /^test_/
77
end
88

9+
def slow
10+
SLUG.match?(/^test_/)
11+
end
12+
913
def fast
1014
SLUG.start_with?('test_')
1115
end
1216

1317
Benchmark.ips do |x|
14-
x.report('String#=~') { slow }
18+
x.report('String#=~') { slower }
19+
x.report('String#match?') { slow } if RUBY_VERSION >= "2.4.0".freeze
1520
x.report('String#start_with?') { fast }
1621
x.compare!
1722
end

0 commit comments

Comments
 (0)