my $writeFh = new FileHandle ">> myout.log";
####
From: "cadetg@googlemail.com"
Message-ID: <1175171070.630366.108750@n59g2000hsh.googlegroups.com>
Date: 29 Mar 2007 05:24:30 -0700
Dear Perl Monks, I am developing at the moment a script which has to
parse 20GB files. The files I have to parse are some logfiles. My
problem is that it takes ages to parse the files. I am doing something
like this:
my %lookingFor;
# keys => different name of one subset
# values => array of one subset
my $fh = new FileHandle "< largeLogFile.log";
while (<$fh>) {
foreach my $subset (keys %lookingFor) {
foreach my $item (@{$subset}) {
if (<$fh> =~ m/$item/) {
my $writeFh = new FileHandle ">> myout.log"; print $writeFh <
$fh>;
}
}
}
I've already tried to speed it up by using the regExp flag=>o by doing
something like this:
$isSubSet=buildRegexp(@allSubSets);
while (<$fh>) {
foreach my $subset (keys %lookingFor) {
if (&$isSubSet(<$fh>)) {
my $writeFh = new FileHandle ">> myout.log";
print $writeFh <$fh>;
}
}
}
sub buildRegexp {
my @R = @_; my $expr = join '||', map { "\$_[0] =~ m/\(To\|is\)\\:\\S
\+\\@\$R[$_ +]/io" } ( 0..$#R );
my $matchsub = eval "sub { $expr }";
if ($@) { $logger->error("Failed in building regex @R: $@"); return
ERROR; }
$matchsub;
}
I don't know how to optimize this more. Maybe it would be possible to
do something with "map"? I think the "o" flag didn't speed it up at
all. Also I've tried to split the one big file into a few small ones
and use some forks childs to parse each of the small ones. Also this
didn't help.
Thanks a lot for your help!
Cheers
-Marco
####
From: bugbear
Message-ID: <460bbcd5$0$8741$ed2619ec@ptn-nntp-reader02.plus.net>
Date: Thu, 29 Mar 2007 14:19:17 +0100
cadetg@googlemail.com wrote:
> Dear Perl Monks, I am developing at the moment a script which has to
> parse 20GB files. The files I have to parse are some logfiles. My
> problem is that it takes ages to parse the files. I am doing something
> like this:
>
> my %lookingFor;
> # keys => different name of one subset
> # values => array of one subset
>
> my $fh = new FileHandle "< largeLogFile.log";
> while (<$fh>) {
> foreach my $subset (keys %lookingFor) {
> foreach my $item (@{$subset}) {
> if (<$fh> =~ m/$item/) {
> my $writeFh = new FileHandle ">> myout.log"; print $writeFh <
> $fh>;
> }
> }
> }
How many key-value pairs does %lookingFor (typically?) have?
BugBear
####
From: "cadetg@googlemail.com"
Message-ID: <1175176945.669754.20700@e65g2000hsc.googlegroups.com>
Date: 29 Mar 2007 07:02:25 -0700
On 29 Mrz., 15:19, bugbear wrote:
> cad...@googlemail.com wrote:
> > Dear Perl Monks, I am developing at the moment a script which has to
> > parse 20GB files. The files I have to parse are some logfiles. My
> > problem is that it takes ages to parse the files. I am doing something
> > like this:
>
> > my %lookingFor;
> > # keys => different name of one subset
> > # values => array of one subset
>
> > my $fh = new FileHandle "< largeLogFile.log";
> > while (<$fh>) {
> > foreach my $subset (keys %lookingFor) {
> > foreach my $item (@{$subset}) {
> > if (<$fh> =~ m/$item/) {
> > my $writeFh = new FileHandle ">> myout.log"; print $writeFh <
> > $fh>;
> > }
> > }
> > }
>
> How many key-value pairs does %lookingFor (typically?) have?
>
> BugBear
The %lookingFor does maybe just have five key value pair but each
value is a reference to an array which is holding in average 20 items.
So in total that makes maybe 100 items for what I have to look for.
Cheers
-Marco
####
From: "Thomas J."
Message-ID: <1175178049.657421.112810@n59g2000hsh.googlegroups.com>
Date: 29 Mar 2007 07:20:49 -0700
cadetg@googlemail.com schrieb:
>
> my %lookingFor;
> # keys => different name of one subset
> # values => array of one subset
>
> my $fh = new FileHandle "< largeLogFile.log";
> while (<$fh>) {
> foreach my $subset (keys %lookingFor) {
> foreach my $item (@{$subset}) {
> if (<$fh> =~ m/$item/) {
> my $writeFh = new FileHandle ">> myout.log"; print $writeFh <
> $fh>;
> }
> }
> }
>
Your code will "copy" the following lines from "lagreLogFile.log"
after successful patternmatch into "myout.log"
This may be time-consuming... ...and possible not what you expected?
(use $_ instead of <$fh> in your "if" and in your "print")
REs may lead to "endless matching". Please show some samples.
study may/may_not help before patternmatching. (perldoc -f study)
Thomas
####
From: Uri Guttman
Message-ID:
Date: Thu, 29 Mar 2007 09:50:37 -0500
>>>>> "cc" == cadetg@googlemail com writes:
cc> Dear Perl Monks, I am developing at the moment a script which has to
cc> parse 20GB files. The files I have to parse are some logfiles. My
cc> problem is that it takes ages to parse the files. I am doing something
cc> like this:
this isn't perlmonks. that is a web site community. this is usenet.
cc> my %lookingFor;
cc> # keys => different name of one subset
cc> # values => array of one subset
cc> my $fh = new FileHandle "< largeLogFile.log";
FileHandle is an old and deprecated module. where did you learn to use
it? you can just do basic open as you don't need any OO here. also
ALWAYS check for errors on opens.
cc> while (<$fh>) {
don't use plain while to read lines. the proper idiom is:
while( my $line = <$fh> ) {
cc> foreach my $subset (keys %lookingFor) {
that makes no sense. keys are strings. they are not array refs. yet the
line below dereferences the key into an array. which means you are not
using strict and you are testing for wrong stuff.
cc> foreach my $item (@{$subset}) {
why the two loops? since you always look at all the items for each line,
factor out the items list to before the loops:
my @items = map @$_, values %lookingFor ;
cc> if (<$fh> =~ m/$item/) {
that is very wrong. it reads a new line in for each match in the
subset. the line from the while is in $_ at the moment.
cc> my $writeFh = new FileHandle ">> myout.log"; print $writeFh <
cc> $fh>;
why are you opening the output file EACH time you want to print? just
open it before the loops and print to it. my previous advice on opens
applies here too.
cc> I've already tried to speed it up by using the regExp flag=>o by doing
cc> something like this:
forget speed for now. your code is broken. are getting any useful output
at all? i can't see how as you are looking for stuff with broken code.
uri
--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
####
From: Michele Dondi
Message-ID:
Date: Sat, 31 Mar 2007 13:44:41 +0200
On Thu, 29 Mar 2007 09:50:37 -0500, Uri Guttman
wrote:
> cc> if (<$fh> =~ m/$item/) {
>
>that is very wrong. it reads a new line in for each match in the
Unless he really wanted to do so. Of course, all odds are against this
remote possibility. :-)
Michele
--
{$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
(($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^##
From: "J. Gleixner"
Message-ID: <460bd4d0$0$494$815e3792@news.qwest.net>
Date: Thu, 29 Mar 2007 10:01:36 -0500
cadetg@googlemail.com wrote:
> Dear Perl Monks, I am developing at the moment a script which has to
> parse 20GB files. The files I have to parse are some logfiles. My
> problem is that it takes ages to parse the files. I am doing something
> like this:
You might be better off using a large egrep and/or by simplifying your
items. e.g. if your item contained 'abc' and 'abcd', you would only
have to search for 'abc'.
>
> my %lookingFor;
> # keys => different name of one subset
> # values => array of one subset
>
> my $fh = new FileHandle "< largeLogFile.log";
> while (<$fh>) {
> foreach my $subset (keys %lookingFor) {
> foreach my $item (@{$subset}) {
> if (<$fh> =~ m/$item/) {
> my $writeFh = new FileHandle ">> myout.log"; print $writeFh <
> $fh>;
> }
Open it once, before the while, and write $_, not <$fh>.
print $writeFh $_ if /$item/;
> }
> }
####
From: "Mumia W."
Message-ID:
Date: Thu, 29 Mar 2007 16:03:25 GMT
On 03/29/2007 07:24 AM, cadetg@googlemail.com wrote:
> Dear Perl Monks, I am developing at the moment a script which has to
> parse 20GB files. The files I have to parse are some logfiles. My
> problem is that it takes ages to parse the files. I am doing something
> like this:
>
> my %lookingFor;
> # keys => different name of one subset
> # values => array of one subset
>
> my $fh = new FileHandle "< largeLogFile.log";
> [1:] while (<$fh>) {
> foreach my $subset (keys %lookingFor) {
> foreach my $item (@{$subset}) {
> [2:] if (<$fh> =~ m/$item/) {
You are aware that line 2 reads in a new chunk from $fh, and the old
chunk read on line 1 is forgotten, don't you?
> my $writeFh = new FileHandle ">> myout.log"; print $writeFh <
> $fh>;
You can open the write filehandle once and keep it open til you are done.
> }
> }
> }
>
> I've already tried to speed it up by using the regExp flag=>o by doing
> something like this:
>
> $isSubSet=buildRegexp(@allSubSets);
> while (<$fh>) {
> foreach my $subset (keys %lookingFor) {
> if (&$isSubSet(<$fh>)) {
> my $writeFh = new FileHandle ">> myout.log";
> print $writeFh <$fh>;
> }
> }
> }
> sub buildRegexp {
> my @R = @_; my $expr = join '||', map { "\$_[0] =~ m/\(To\|is\)\\:\\S
> \+\\@\$R[$_ +]/io" } ( 0..$#R );
> my $matchsub = eval "sub { $expr }";
> if ($@) { $logger->error("Failed in building regex @R: $@"); return
> ERROR; }
> $matchsub;
> }
>
> I don't know how to optimize this more. Maybe it would be possible to
> do something with "map"? I think the "o" flag didn't speed it up at
> all. Also I've tried to split the one big file into a few small ones
> and use some forks childs to parse each of the small ones. Also this
> didn't help.
>
> Thanks a lot for your help!
>
> Cheers
> -Marco
>
It might not be possible to get much faster with such large files, but
try this out:
#!/usr/bin/perl
use strict;
use warnings;
use FileHandle;
use Data::Dumper;
use Alias;
my %lookingFor = (
houseware => [qw(wallpaper hangers doorknobs)],
);
my %lookingForRx = lookingForRx(%lookingFor);
my $fh = new FileHandle '< largeLogFile.log';
my $writeFh = new FileHandle '> myout.log';
while (my $line = <$fh>) {
foreach my $subset (keys %lookingForRx) {
if ($line =~ /$lookingForRx{$subset}/) {
print $writeFh $line;
}
}
}
$writeFh->close;
$fh->close;
#####################################
sub lookingForRx {
our (%oldHash, @oldArray);
local %oldHash = @_;
local @oldArray;
my %hash;
foreach my $subset (keys %oldHash) {
alias oldArray => $oldHash{$subset};
my $rx = do { local $" = '|'; "(@oldArray)" };
$hash{$subset} = qr/$rx/;
}
%hash;
}
__END__
I haven't really tested this other than to make sure it compiles.
####
From: "John W. Krahn"
Message-ID: <43UOh.28203$x9.8743@edtnps89>
Date: Thu, 29 Mar 2007 19:02:24 GMT
Mumia W. wrote:
> On 03/29/2007 07:24 AM, cadetg@googlemail.com wrote:
>> Dear Perl Monks, I am developing at the moment a script which has to
>> parse 20GB files. The files I have to parse are some logfiles. My
>> problem is that it takes ages to parse the files. I am doing something
>> like this:
>>
>> my %lookingFor;
>> # keys => different name of one subset
>> # values => array of one subset
>>
>> my $fh = new FileHandle "< largeLogFile.log";
>> [1:] while (<$fh>) {
>> foreach my $subset (keys %lookingFor) {
>> foreach my $item (@{$subset}) {
>> [2:] if (<$fh> =~ m/$item/) {
>
> You are aware that line 2 reads in a new chunk from $fh, and the old
> chunk read on line 1 is forgotten, don't you?
It is the other way around. "while (<$fh>) {" read a line and stores it in $_
so it is still around, while "if (<$fh> =~ m/$item/) {" reads another line and
binds it to the regular expression and then discards it.
>> my $writeFh = new FileHandle ">> myout.log"; print $writeFh <
>> $fh>;
And a third line is read from the file and printed out.
John
--
Perl isn't a toolbox, but a small machine shop where you can special-order
certain sorts of tools at low cost and in short order. -- Larry Wall
####
From: "Mumia W."
Message-ID:
Date: Thu, 29 Mar 2007 21:40:01 GMT
On 03/29/2007 02:02 PM, John W. Krahn wrote:
>
> It is the other way around. "while (<$fh>) {" read a line and stores it in $_
> so it is still around, while "if (<$fh> =~ m/$item/) {" reads another line and
> binds it to the regular expression and then discards it.
>
> [...]
Oops, you're right. The "while (<$fh>)" magic confused me.