Speeding up P::RD using a queue...

[email protected] ("Yves Orton")
Newsgroups perl.recdescent
Message-ID <[email protected]>
on 2001/12/11 18:55 Terrence Brannon wrote:

>** this recent discussion: http://www.perlmonks.org/index.pl?node_id=130656

Heh. Ironic to see my thread on perlmonks posted here as a link. :-) 
Nevertheless I still have yet to get a satisfactory answer to the post I 
made there http://www.perlmonks.org/index.pl?node_id=130714

Basically the idea was to speed up P::RD by making it process line by line 
from a queue.  Each time a rule succesfully fired it would pull a new line 
from the queue and append it to $text.  Which worked for my test data set 
when shuffled, but not when it was sorted.

use strict;
use warnings;
use Parse::RecDescent;
use Data::Dumper;

our $RD_TRACE=1;

my $Grammar=<<'END_GRAMMAR';

{my $company=""}

startrule   :   file

file        :   header record(s?) trailer_t
                {
                    
$return={header=>$item[1],records=>$item[2],count=>$item[3]};
                }

header      :   header_t data_t
                {
                    $return={company=>$item[1],code=>$item[2]};
                      $text.=shift @::text;
                      print "Company Set to $company\n Text=$text";
                }

record      :   valid_record | <error>

valid_record:   type_t ',' number_t ',' number_t(?) ',' "$company"
                {
                    $return=[ $item[1],$item[3],@{$item[5]} ? $item[5] : 
undef ];
                    $text.=shift @::text; #grab a line from queue
                    print "Text=$text";
                }

header_t    :   /HDR\w+/ {$return=substr($item[1],3); $company=$return;}
trailer_t   :   /TLR\d+/ {$return=substr($item[1],3)}

data_t      :   /\w+/
type_t      :   /ADD(?:RANGE)?|DELETE(?:RANGE)?/
number_t    :   /\d+/

END_GRAMMAR


my $parser = Parse::RecDescent->new($Grammar) or die "Bad grammar!\n";


our @text=<DATA>;

if (defined( my $t=$parser->startrule(shift @text))) {
    print Dumper($t);
} else {
    print "Bad text!\n";
}


__DATA__
HDRCOMPNAME BIG000OLD111IDENTIFIER1020301WITH1010LOTS1010OF1010CRAP
ADD,1234567890,,COMPNAME
ADD,1234567891,,COMPNAME
ADD,1234567892,,COMPNAME
ADDRANGE,1468,1680,COMPNAME
ADDRANGE,2468,2680,COMPNAME
ADDRANGE,3468,3680,COMPNAME
DELETE,987654321,,COMPNAME
DELETE,987654322,,COMPNAME
DELETE,987654323,,COMPNAME
DELETERANGE,13579,13599,COMPNAME
DELETERANGE,23579,23599,COMPNAME
DELETERANGE,33579,33599,COMPNAME
TLR000012

Now weirdly it seems to perform as expected if the same data is organized as 
so:

HDRCOMPNAME BIG000OLD111IDENTIFIER1020301WITH1010LOTS1010OF1010CRAP
ADD,1234567890,,COMPNAME
ADDRANGE,1468,1680,COMPNAME
DELETE,987654321,,COMPNAME
DELETERANGE,13579,13599,COMPNAME
ADD,1234567891,,COMPNAME
ADDRANGE,2468,2680,COMPNAME
DELETE,987654322,,COMPNAME
DELETERANGE,33579,33599,COMPNAME
ADD,1234567892,,COMPNAME
ADDRANGE,3468,3680,COMPNAME
DELETE,987654323,,COMPNAME
DELETERANGE,23579,23599,COMPNAME
TLR000012

A trace of the the two is identical until the second record is encountered, 
where the first data simply reports that it was able to find only 1 record, 
and the second parses the whole lot.

I was able to overcome this by changing valid_rule to

valid_record:   {
			while ($lines<4) {
				$text.=shift(@::text);
				$lines++;
			}
                	warn "Text=$text";
                }
		type_t ',' number_t ',' number_t(?) ',' "$company"
                {
                	$return=[
                                 $item[2],
                                 $item[4],
                                 @{$item[6]} ? $item[6]->[0] : undef
                                ];
                	$lines--;
                }

And adding a my declaration for $line to the preparse action.  Note that 
this tries to keep 4 lines in $text at all times, 3 did not work!. I havent 
the foggiest why this works, nor what is going on, and accordingly I dont 
trust it in the slightest. (It is notable that there are triplets of the 
same record type, is n+1 relevent? I dont know)  It was suggested it had to 
do with changes to $text only applying if a rule is successful, but this 
does not explain why record(s?) fails after the first record when type_t is 
the same on consecutive records, but not when it is different.

Anyway, any thoughts or ideas would be welcome.

Oh and any workable ideas that I get will be forwarded onto perlmonks unless 
requested not to.

Yves


_________________________________________________________________
Send and receive Hotmail on your mobile device: http://mobile.msn.com
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.