I just read about Regexp.match?('string')
for Ruby 2.4 and was very excited to see the results! But when I tried it out in my application, I hardly saw any gains.
str = 's'
Benchmark.bm do |b|
b.report(".match ") { 100000.times { 'string'.match /s/ } }
b.report(".match? ") { 100000.times { 'string'.match? /s/ } }
b.report(".match dynamic ") { 100000.times { 'string'.match /#{str}/ } }
b.report(".match? dynamic") { 100000.times { 'string'.match? /#{str}/ } }
end
user system total real
.match 0.140000 0.000000 0.140000 ( 0.143658)
.match? 0.020000 0.000000 0.020000 ( 0.029628)
.match dynamic 0.370000 0.010000 0.380000 ( 0.371935)
.match? dynamic 0.260000 0.010000 0.270000 ( 0.278614)
From the Benchmark, we see a tremendous gain from .match
to .match?
, but once i start dynamically creating complicated regex as my app requires, I'm loosing a lot of the gains.
My question is, why is there such a drastic difference and can I somehow create dynamic regexp to utilize the performance of .matches?
in the example below? I tested my benchmarks using ruby 2.4.2p198
str = 'my text with words'
reg_str = '((^|[\s\"“])(cherry pie|cherry pies)($|[\s\"”\.\,\:\?\!])|(\#(cherrypie|cherrypies)($|\s|\#|\.|\,|\:|\?|\!)))'
puts Benchmark.measure {
100000.times { str.match? /#{reg_str}/i }
}
9.380000 0.010000 9.390000 ( 9.403821)
puts Benchmark.measure {
100000.times { str.match? /((^|[\s\"“])(cherry pie|cherry pies)($|[\s\"”\.\,\:\?\!])|(\#(cherrypie|cherrypies)($|\s|\#|\.|\,|\:|\?|\!)))/i }
}
0.020000 0.000000 0.020000 ( 0.017900)
The speed improvement of
match?
comes from not allocating the MatchData objects and globals like$1
. It just returnstrue
orfalse
. You can't usematch?
if you need to return something from the regex.match?
won't be any faster at compiling regex-strings intoRegexp
objects.Perhaps in your code you can first create the regexes and then use those in the loop instead of constantly recreating them: