What is "/o" really for?
Using a variable in a regular expression match forces a re-evaluation
(and perhaps recompilation) each time the regular expression is
encountered. The "/o" modifier locks in the regex the first time it's
used. This always happens in a constant regular expression, and in fact,
the pattern was compiled into the internal format at the same time your
entire program was.
Use of "/o" is irrelevant unless variable interpolation is used in the
pattern, and if so, the regex engine will neither know nor care whether
the variables change after the pattern is evaluated the *very first*
time.
"/o" is often used to gain an extra measure of efficiency by not
performing subsequent evaluations when you know it won't matter (because
you know the variables won't change), or more rarely, when you don't
want the regex to notice if they do.
For example, here's a "paragrep" program:
$/ = ''; # paragraph mode
$pat = shift;
while (<>) {
print if /$pat/o;
}
####
#!/usr/bin/perl -w
use strict;
use Benchmark qw(cmpthese);
my $pattern=join "|",qw(a ab abc abcde ef gh ghij qrst nqmz stuv);
my $qr=qr/$pattern/;
my @candidates=qw(abc zzz stuv asasdfasdfaf qqqqqqqqqqqqqqqq lkasjh adsd qqqqqqqqqqqqabc);
sub preComp {
my $result=scalar grep /$pattern/o,@candidates;
return $result;
}
sub preCompQR {
my $result=scalar grep /$qr/o,@candidates;
return $result;
}
sub noPrecomp {
my $result=scalar grep /$pattern/,@candidates;
return $result;
}
print "Working from pattern '$pattern', qr='$qr'\n";
print "preComp finds ",preComp(),"\n";
print "preCompQR finds ",preCompQR(),"\n";
print "noPrecomp finds ",noPrecomp(),"\n";
cmpthese(-3,
{
preComp => \&preComp,
preCompQR => \&preCompQR,
noPrecomp => \&noPrecomp
}
);
####
Working from pattern 'a|ab|abc|abcde|ef|gh|ghij|qrst|nqmz|stuv', qr='(?-xism:a|ab|abc|abcde|ef|gh|ghij|qrst|nqmz|stuv)'
preComp finds 6
preCompQR finds 6
noPrecomp finds 6
Benchmark: running noPrecomp, preComp, preCompQR, each for at least 3 CPU seconds...
noPrecomp: 4 wallclock secs ( 3.09 usr + 0.01 sys = 3.10 CPU) @ 33414.22/s (n=103417)
preComp: 4 wallclock secs ( 3.24 usr + 0.01 sys = 3.25 CPU) @ 35360.06/s (n=115097)
preCompQR: 2 wallclock secs ( 3.08 usr + 0.02 sys = 3.10 CPU) @ 35094.39/s (n=108933)
Rate noPrecomp preCompQR preComp
noPrecomp 33414/s -- -5% -6%
preCompQR 35094/s 5% -- -1%
preComp 35360/s 6% 1% --