I'm glad you brought up this point. I too am a huge fan of qr; however, I think this situation is a perfect use of the /o operator. I assumed that the snippet the author posted was but a morsal of his actual code; he probably uses dozens of patterns and thousands of lines of input. Compiling the regex with /o (rather than building it with qr) is ideal for this situation where a single regex is to be applied to huge amounts of data. It will result in a speed boost. For instance, I modified my earlier code and ran this benchmark:
use Benchmark;
timethese(1000, {
Slasho => \&withslasho,
None => \&without,
qr => \&withqr
});
sub withslasho
{
my $str1 = 'ABCBXBCA';
my $str2 = 'APCBXBCAC';
my @array = ($str1, $str2) x 500;
my @patterns = ('B.B', 'CB')x10;
my $pat = join '|',@patterns;
foreach my $string (@array)
{
if($string =~ /($pat)/o)
{
# do a pattern lookup to see which pattern matched.
my $matched;
foreach my $p (@patterns)
{
if ($1 =~ /$p/)
{
$matched = $p;
last;
}
}
}
}
}
sub without
{
my $str1 = 'ABCBXBCA';
my $str2 = 'APCBXBCAC';
my @array = ($str1, $str2) x 500;
my @patterns = ('B.B', 'CB')x10;
my $pat = join '|',@patterns;
foreach my $string (@array)
{
if($string =~ /($pat)/)
{
# do a pattern lookup to see which pattern matched.
my $matched;
foreach my $p (@patterns)
{
if ($1 =~ /$p/)
{
$matched = $p;
last;
}
}
}
}
}
sub withqr
{
my $str1 = 'ABCBXBCA';
my $str2 = 'APCBXBCAC';
my @array = ($str1, $str2) x 500;
my @patterns = ('B.B', 'CB')x10;
my $pat = join '|',@patterns;
$pat = qr/$pat/;
foreach my $string (@array)
{
if($string =~ /($pat)/)
{
# do a pattern lookup to see which pattern matched.
my $matched;
foreach my $p (@patterns)
{
if ($1 =~ /$p/)
{
$matched = $p;
last;
}
}
}
}
}
Which outputs:
Benchmark: timing 1000 iterations of None, Slasho, qr...
None: 70 wallclock secs (69.60 usr + 0.00 sys = 69.60 CPU) @ 14
+.37/s (n=1000)
Slasho: 61 wallclock secs (61.24 usr + 0.00 sys = 61.24 CPU) @ 16
+.33/s (n=1000)
qr: 66 wallclock secs (65.80 usr + 0.00 sys = 65.80 CPU) @ 15
+.20/s (n=1000)
|