我的目标是对流程中出现的数据(基于行)进行一些正则表达式和一些处理。由于我已经在perl中获得了大量工具,因此我决定使用perl来解决我的问题。
让我们说一个输出大文件的过程,例如:
cat LARGEFILE.txt | grep"一个字符串"
显然我要打电话的过程不是" cat"但输出一堆行(通常是100 GB的数据)的东西。
我怀疑我的perl程序的性能,并开始将代码删除到最低限度。我意识到我的问题可能来自于我在perl中读取命令输出的方式。
这是我的perl脚本:
#!/usr/bin/perl
use strict;
open my $fh, "cat LARGE.txt |";
while (<$fh>) {
print $_ if $_ =~ qr/REGEX NOT TO BE FOUND/o;
}
我决定将我的程序与一个简单的bash命令进行比较:
cat LARGE.txt | grep "REGEX NOT TO BE FOUND"
结果:
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
在我的示例中,LARGE.txt文件大约是1.3GB。
我知道perl解决方案可能比cat | grep
示例慢,但我没想到会有太大差异。
我的阅读命令输出方式有问题吗?
P.S。我在Linux机器上使用perl v5.10.1
答案 0 :(得分:1)
你可以试试sysread:
(被盗: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";
}