Strange performance problem inside POE
Jan Sundberg <[email protected]>
| Newsgroups | gmane.comp.lang.perl.poe |
|---|---|
| Message-ID | <[email protected]> |
Hello.
I'm writing a regexp based parser based on the perlop manpage /\G.../gc
example:
LOOP:
{
print(" digits"), redo LOOP if
/\G\d+\b[,.;]?\s*/gc;
print(" lowercase"), redo LOOP if
/\G[a-z]+\b[,.;]?\s*/gc;
print(" UPPERCASE"), redo LOOP if
/\G[A-Z]+\b[,.;]?\s*/gc;
print(" Capitalized"), redo LOOP if
/\G[A-Z][a-z]+\b[,.;]?\s*/gc;
print(" MiXeD"), redo LOOP if
/\G[A-Za-z]+\b[,.;]?\s*/gc;
print(" alphanumeric"), redo LOOP if
/\G[A-Za-z0-9]+\b[,.;]?\s*/gc;
print(" line-noise"), redo LOOP if
/\G[^A-Za-z0-9]+/gc;
print ". That's all!\n";
}
In converts long PDU strings to anonymous hashes using:
# testing wrapper
while (<>) {
chomp;
my $str = $_;
my $h = dict(\$str);
print Dumper($h);
}
# converts a string to a nested anonymous hash
sub dict {
my $msg = shift;
$$msg =~ /\G\{/gc;
my $h = {};
while ($$msg =~ /\G\s*(\S+?)\s*=\s*/gc) {
my $key = $1;
if ($$msg =~ /\G(?=\{)/gc) {
$h->{$key} = dict($msg);
} elsif ($$msg =~ /\G([^\|\}]*)/gc) {
my $value = $1;
$h->{$key} = $value;
}
return $h if $$msg =~ /\G\}/gc;
$$msg =~ /\G\|/gc;
}
}
It's *very* fast due to nonexistent string manipulation and pos() offset
indexing.
Here's the strange thing: if I use the *exactly* same code inside a POE
Filter it becomes more than 10 times slower!
A small SmallProf comparison:
FAST version in a simple script:
0 0.00000 0.00000 22:sub dict {
853 0.00051 0.00000 23: my $msg = shift;
853 0.00044 0.00000 24: $$msg =~ /\G\{/gc;
853 0.00105 0.00000 25: my $h = {};
853 0.00373 0.02000 26: while ($$msg =~
/\G\s*(\S+?)\s*=\s*/gc) {
10053 0.03222 0.15000 27: my $key = $1;
10053 0.02309 0.09000 28: if ($$msg =~ /\G(?=\{)/gc) {
0 0.00000 0.00000 29: $h->{$key} = dict($msg);
0 0.00000 0.00000 30:# print "DICT $key => ", Dumper($h-
0 0.00000 0.00000 31: } elsif ($$msg =~ /\G([^\|\}]*)/gc) {
9201 0.01445 0.17000 32: my $value = $1;
9201 0.03373 0.13000 33: $h->{$key} = $value;
0 0.00000 0.00000 34:# print "SCALAR $key => $value\n";
0 0.00000 0.00000 35: }
10053 0.01924 0.17000 36: return $h if $$msg =~ /\G\}/gc;
9200 0.03602 0.16000 37: $$msg =~ /\G\|/gc;
0 0.00000 0.00000 38: }
0 0.00000 0.00000 39:}
SLOW version in a POE/Filter subclass:
0 0.00000 0.00000 65:sub dict {
871 0.00127 0.01000 66: my $msg = shift;
871 0.29427 0.41000 67: $$msg =~ /\G\{/gc;
871 0.00177 0.00000 68: my $h = {};
871 0.29943 0.41000 69: while ($$msg =~
/\G\s*(\S+?)\s*=\s*/gc) {
10410 0.05206 0.29000 70: my $key = $1;
10410 3.74933 3.80000 71: if ($$msg =~ /\G(?=\{)/gc) {
0 0.00000 0.00000 72: $h->{$key} = dict($msg);
0 0.00000 0.00000 73:# print "DICT $key => ", Dumper($h-
0 0.00000 0.00000 74: } elsif ($$msg =~ /\G([^\|\}]*)/gc) {
9541 0.03874 0.19000 75: my $value = $1;
9541 0.03370 0.17000 76: $h->{$key} = $value;
0 0.00000 0.00000 77:# print "SCALAR $key => $value\n";
0 0.00000 0.00000 78: }
10410 0.34352 0.59000 79: return $h if $$msg =~ /\G\}/gc;
9539 6.66969 6.42000 80: $$msg =~ /\G\|/gc;
0 0.00000 0.00000 81: }
0 0.00000 0.00000 82:}
None of the PDU strings are tied or blessed. What's happening ? Please help!
Kind regards.
/ Jan Sundberg