I was looping through each subsitution which is inefficient!
Not necessarily. Alternation can disable some optimizations that the regex engine uses. This becomes more noticable on larger strings.
use strict;
use warnings;
use Benchmark qw(cmpthese timethese);
my $orig = "Test: FileNames can't have / \\ and other special characte
+rs";
$orig .= 'a' x 1000;
my %substs = qw(
: COLON
/ FSLASH
\\\\ BSLASH
);
sub loop {
my $string = $orig;
$string =~ s/$_/$substs{$_}/g
for keys %substs;
return;
}
my @substs = (
qr/:/ => 'COLON',
qr/\// => 'FSLASH',
qr/\\/ => 'BSLASH',
);
sub loop2 {
my $string = $orig;
$string =~ s/$substs[$_]/$substs[$_ + 1]/g
for map $_ * 2, 0 .. $#substs / 2;
return;
}
my %s = qw(
: COLON
/ FSLASH
\\ BSLASH
);
my $t = join "|", map quotemeta, keys %s;
sub alter {
my $string = $orig;
$string =~ s/($t)/$s{$1}/g;
return;
}
my %tests = (
loop => \&loop,
loop2 => \&loop2,
alter => \&alter,
);
cmpthese(timethese(-2, \%tests));
__END__
Benchmark: running alter, loop, loop2 for at least 2 CPU seconds...
alter: 3 wallclock secs ( 2.42 usr + 0.00 sys = 2.42 CPU) @ 16
+55.39/s (n=4011)
loop: 2 wallclock secs ( 2.13 usr + 0.00 sys = 2.13 CPU) @ 64
+89.92/s (n=13843)
loop2: 2 wallclock secs ( 2.02 usr + 0.00 sys = 2.02 CPU) @ 11
+480.97/s (n=23226)
Rate alter loop loop2
alter 1698/s -- -72% -86%
loop 6125/s 261% -- -48%
loop2 11811/s 596% 93% --
Note that the code isn't completely equivalent though. Using &loop or &loop2 you can replace a replacement. For instance, if a replacement has a colon in it &alter will leave it there while &loop will change it to "COLON".
ihb
See perltoc if you don't know which perldoc to read!
|