while ($mmap =~ m/^([^\n]*$pat[^\n]\n)/omg) { print $1; }
I found performance was abysmal: 20 seconds to search a 400K file (/usr/share/dict/words) for "foo". Some investigation (and perl -Dr) revealed that the regex engine was finding "foo" in the string very quickly, then was trying every single line preceding it to see if it matched against the remaining regex. I rewrote my simple pattern to:
and runtime went from 20 seconds to .040 seconds.while ($mmap =~ m/$pat/omg) { my $pos = pos $mmap; # Find the beginning and end of this line my $first = rindex($mmap,"\n",$pos)+1; my $last = index($mmap,"\n",$pos)+1; print substr($mmap,$first,$last-$first); }
My question is: is there anything I could have told Perl to give it a hint about how to perform the match, such as "Hey Perl, the ^ is going to be pretty close to $pat, so just search backwards from wherever you find it"?
Here's a full copy of the original program.
#!/usr/bin/perl use warnings; use strict; use Sys::Mmap; our $pat = shift; foreach my $a (@ARGV) { my $mmap; if (! -f $a) { warn "'$a' is not a regular file, skipping\n"; next; } open(F, "< $a") or die "Couldn't open '$a': $!\n"; mmap($mmap, 0, PROT_READ, MAP_SHARED, F) or die "mmap error: $!\n"; while ($mmap =~ m/^([^\n]*$pat[^\n]\n)/omg) { print $1; } munmap($mmap) or die "mmunmap error: $!\n"; close(F) or die "Couldn't close '$a': $!\n"; }
In reply to Surprisingly poor regex performance by sgifford
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |