in reply to Re: Pulling data out of { }
in thread Pulling data out of { }

Or you could avoid ifs and whiles completely:
use strict; use warnings; use Parse::RecDescent (); my $grammar = <<'__END_OF_GRAMMAR__'; { use strict; use warnings; sub dequote { local $_ = @_ ? $_[0] : $_; s/^"//; s/"$//; s/\\(.)/$1/sg; return $_; } } parse : record(s?) /\Z/ { [ map @$_, @{$item[1]} ] } record : 'instance' 'of' 'Win32_LogicalDisk' '{' field(s?) '}' ';' { my $name; my %record; %record = map @$_, @{$item[5]}; $name = delete($record{Name}); $name ? [ $name, \%record ] : undef } field : key '=' val ';' { [ $item[1], $item[3] ] } key : IDENT val : QSTRING IDENT : /\w+/ QSTRING : /"(?:[^\\"]|\\.)*"/ { dequote($item[1]) } # guessing. __END_OF_GRAMMAR__ my $p = Parse::RecDescent->new($grammar) or die("Bad grammar\n"); my $text; { local $/; $text = <DATA>; } my $data = $p->parse($text) or die("Bad data\n"); require Data::Dumper; print(Data::Dumper::Dumper($data));

Same output as the program in the parent post.

Replies are listed 'Best First'.
Re^3: Pulling data out of { }
by BrowserUk (Patriarch) on Jan 17, 2006 at 04:56 UTC

    Out of interest, are you doing something unusual here that makes this grammer run so slowly?

    For example, is your dequote sub being eval'd into existance every time it is used or something similar?

    Also, is there any particular benefit in doing

    require Data::Dumper; print(Data::Dumper::Dumper($data));

    Instead of the usual use Data::Dumper/print Dumper $data?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      The sub is only eval'ed once per new.

      I bet it (->parse) doesn't run slowly. The time is probably spent parsing the grammar, compiling it into Perl code, and compiling the Perl code (->new). Parse::RecDescent shouldn't be used directly in production code. Modules created by Parse::RecDescent's Precompile method should be used instead.

      There is no benefit to using require here. I don't like to use use at spots other than at the top of the package, and I wanted to group the testing code together.

        The time is probably spent parsing the grammar,

        Hmm. Seems not. I just put separate timings around the ->new and the ->parse and the former took just 1 second.

        The other day I wanted to compare the time taken and resilience of our solutions. It doesn't matter a jot for the OPs application as there are a maximum of 26 drives, but I was interested in the comparative performance of my solution.

        Rather than doing a full benchmark, I thought I'd just create a file with enough data that the timings came out in seconds. I tried mine against 676 records ('aa'..'zz'), but it was well under a second so I generated 17,576 records (<c>'aaa'..'zzz'/<c>) and it took around 5 seconds.

        I then started your Parse::RecDescent solution against the same file and went off and did something else. When I returned, it had already consumed well over an hour of cpu and eventually finished having consumed 98 minutes of cpu on a quiescent system! So in 1 1/2 hours or so time I should get how long the parsing takes.

        I know P::RD isn't the quickest thing on the block, but this difference is way greater than the last time I measured. There has to be something about this particular grammar that is causing it to go so slowly, but I'm not sufficiently familiar with P::RD to recognise what?


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.