Home > Blockchain >  Perl: speed of s/// with variable in replacement
Perl: speed of s/// with variable in replacement

Time:08-04

This:

while($read=sysread(STDIN,$buf,32760)) {
    $buf=~s/\r/posttag\rpretag\t/go;
    $buf=~s/\n/posttag\npretag\t/go;
    syswrite(STDOUT,$buf);
}

delivers ~200 MB/s on my system.

This:

my $pretag = "pretag";
my $posttag = "posttag";
while($read=sysread(STDIN,$buf,32760)) {
    $buf=~s/\r/$posttag\r$pretag\t/go;
    $buf=~s/\n/$posttag\n$pretag\t/go;
    syswrite(STDOUT,$buf);
}

delivers ~100 MB/s on my system.

Why?

I thought that when I had used /o it should not matter if the content is a variable or a fixed string. Is there an easy way I can get the speed of the first?

CodePudding user response:

Are you sure that regexp recompilation is to blame? You can get information about what perl is doing with your regexps using

use re 'debug';

In second case you introduce interpolated string in s//HERE/ and perl interpolates it with each iteration.

Try to rewrite like

my $pretag = 'pretag';
my $posttag = 'posttag';
my $first_replace = "$posttag\r$pretag\t";
my $second_replace = "$posttag\n$pretag\t";
while($read=sysread(STDIN,$buf,32760)) {
    $buf=~s/\r/$first_replace/go;
    $buf=~s/\n/$second_replace/go;
    syswrite(STDOUT,$buf);
}

CodePudding user response:

Per the perlop documentation for the /o flag, emphasis added:

"s/PATTERN/REPLACEMENT/msixpodualngcer"

If you want the pattern compiled only once the first time the variable is interpolated, use the "/o" option.

Therefore /o is only relevant to the pattern, not the replacement. Even then some programmers consider /o to be a problem, and will not use it, with the typical sentiment running along the lines of:

< pragma-> perlre#Modifiers: o - pretend to optimize your code, but actually introduce bugs

If I had to interpolate the Right-Hand-Side or replacement in advance, I'd probably use Sub::Quote or similar to turn the RHS into static strings.

  •  Tags:  
  • perl
  • Related