Greed is bad. More specifically, greedy quantifiers for some regexes are bad; they can slow things down.
I compared your regex (called greedy) with a version using the +? nongreedy qualifier, both against your string (where both will give correct results) and a much longer string, where the non-greedy version will match the first 3 codes, and the greedy version will match the first code and the last 2.
$ perl testGreed.pl
Benchmark: running greedyLong, greedyShort, notGreedyLong, notGreedySh
+ort,
each for at least 3 CPU seconds...
greedyLong: 3 wallclock secs ( 3.00 usr + 0.00 sys = 3.00 CPU) @ 42
+264.23/s (n=127004)
greedyShort: 4 wallclock secs ( 3.20 usr + 0.01 sys = 3.21 CPU) @ 8
+8692.45/s (n=284348)
notGreedyLong: 4 wallclock secs ( 3.13 usr + 0.01 sys = 3.14 CPU) @
+ 46018.76/s (n=144729)
notGreedyShort: 3 wallclock secs ( 2.99 usr + 0.01 sys = 3.00 CPU)
+@ 101593.68/s (n=305289)
Rate greedyLong notGreedyLong greedyShort notG
+reedyShort
greedyLong 42264/s -- -8% -52%
+ -58%
notGreedyLong 46019/s 9% -- -48%
+ -55%
greedyShort 88692/s 110% 93% --
+ -13%
notGreedyShort 101594/s 140% 121% 15%
+ --
As you can see, the non-greedy version runs considerably faster, since it doesn't wind up trying as many alternatives (a.k.a. backtracking).
Here's the comparison code:
#!/usr/bin/perl -w
use strict;
use Benchmark qw(cmpthese);
my $i=0;
my $varshort = "xxx:12345 yyy:54321 zzz:13245";
my $varlong = ("$varshort "x120);
sub greedy {
$_[0]=~m/.+\:(.+?)\s.+\:(.+?)\s.+\:(.+?)/;
}
sub notGreedy {
$_[0]=~m/.+\:(.+?)\s.+?\:(.+?)\s.+?\:(.+?)/;
}
sub greedyShort {
greedy($varshort);
}
sub greedyLong {
greedy($varlong);
}
sub notGreedyShort {
notGreedy($varshort);
}
sub notGreedyLong {
notGreedy($varlong);
}
cmpthese(-3,
{
greedyShort => \&greedyShort,
greedyLong => \&greedyLong,
notGreedyShort => \¬GreedyShort,
notGreedyLong => \¬GreedyLong,
}
);
Those results were with 5.6.1 on Cygwin, your results may vary.
--
Mike
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.