My goal is to do some regex and some processing on the data (line based) that comes out of a process. Since I've already got a bunch of tool in perl, I decided to use perl to solve my problem.
Let's say a process that output a large file for example :
cat LARGEFILE.txt | grep "A String"
Obviously the process I want to call is not "cat" but something that output a bunch of lines (typically 100 GB of data).
I had doubt about the performance of my perl program and I started to strip down code to the minimum. I realized that my problem might come from the way I read the output from the command in perl.
Here's my perl script :
#!/usr/bin/perl
use strict;
open my $fh, "cat LARGE.txt |";
while (<$fh>) {
print $_ if $_ =~ qr/REGEX NOT TO BE FOUND/o;
}
I decided to compare my program with a simple bash command :
cat LARGE.txt | grep "REGEX NOT TO BE FOUND"
Results :
time cat LARGE.txt | grep "REGEX NOT TO BE FOUND"
real 0m0.615s
user 0m0.352s
sys 0m0.873s
time ./test.pl
real 0m37.339s
user 0m36.621s
sys 0m1.766s
In my example, LARGE.txt file is about 1.3GB.
I understand that the perl solution might be slower than the cat | grep example, but I was not expecting that much difference.
Is there something wrong with my way of reading the output of a command ?
P.S. I use perl v5.10.1 on a Linux box
You could try out sysread:
(stolen from: http://www.perlmonks.org/?node_id=457046)
use warnings;
use strict;
use Data::Dumper;
my $filename = "test.txt";
die "filename not found\n" unless -f $filename;
my $size = -s $filename;
my $total_read = 0;
open my $fh, "<", $filename or die "can't open $filename\n";
binmode($fh);
my $bufsize = 8192; # typical size for i/o buffers
my ( $databuf, $readbuf, $nread );
while (( $nread = sysread( $fh, $readbuf, $bufsize )) > 0 ) {
$databuf .= $readbuf;
process_lines_from_buffer(\$databuf);
}
print "initial size: $size\n";
sub process_lines_from_buffer{
### to make it efficient do not use a named variable for the buffer
return undef if ! defined $_[0];
while (${$_[0]} =~ s!(.*?)\n!!){
### do your processing
process_line(\$1);
}
}
sub process_line {
print ${$_[0]}."\n";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With