New*_*erl 8 io perl performance conditional input
我从Perl中的tab标签文件中抓取了一些列.该文件的第一行与其他行完全不同,因此我想尽可能快速有效地跳过该行.
这就是我到目前为止所拥有的.
my $firstLine = 1;
while (<INFILE>){
if($firstLine){
$firstLine = 0;
}
else{
my @columns = split (/\t+/);
print OUTFILE "$columns[0]\t\t$columns[1]\t$columns[2]\t$columns[3]\t$columns[11]\t$columns[12]\t$columns[15]\t$columns[20]\t$columns[21]\n";
}
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来做到这一点,也许没有$ firstLine?或者有没有办法直接从第2行开始阅读INFILE?
提前致谢!
Sch*_*ern 29
让我们得到一些数据.我对每个人的技术进行了基准测试......
#!/usr/bin/env perl
sub flag_in_loop {
my $file = shift;
open my $fh, $file;
my $first = 1;
while(<$fh>) {
if( $first ) {
$first = 0;
}
else {
my $line = $_;
}
}
return;
}
sub strip_before_loop {
my $file = shift;
open my $fh, $file;
my $header = <$fh>;
while(<$fh>) {
my $line = $_;
}
return;
}
sub line_number_in_loop {
my $file = shift;
open my $fh, $file;
while(<$fh>) {
next if $. < 2;
my $line = $_;
}
return;
}
sub inc_in_loop {
my $file = shift;
open my $fh, $file;
my $first;
while(<$fh>) {
$first++ or next;
my $line = $_;
}
return;
}
sub slurp_to_array {
my $file = shift;
open my $fh, $file;
my @array = <$fh>;
shift @array;
return;
}
my $Test_File = "/usr/share/dict/words";
print `wc $Test_File`;
use Benchmark;
timethese shift || -10, {
flag_in_loop => sub { flag_in_loop($Test_File); },
strip_before_loop => sub { strip_before_loop($Test_File); },
line_number_in_loop => sub { line_number_in_loop($Test_File); },
inc_in_loop => sub { inc_in_loop($Test_File); },
slurp_to_array => sub { slurp_to_array($Test_File); },
};
Run Code Online (Sandbox Code Playgroud)
由于这是I/O,可能受到Benchmark.pm调整能力的影响,我跑了几次并检查我得到了相同的结果.
/usr/share/dict/words是一个2.4兆字节的文件,有大约240k非常短的行.由于我们没有处理线路,因此线路长度无关紧要.
我只在每个例程中做了很少的工作来强调技术之间的差异.我想做一些工作,以便通过改变你阅读文件的方式,为你将获得或失去的性能产生一个现实的上限.
我是在带有SSD的笔记本电脑上做到这一点,但它仍然是笔记本电脑.随着I/O速度的增加,CPU时间变得更加重要.在具有快速I/O的机器上,技术更为重要.
这是每个例程每秒读取文件的次数.
slurp_to_array: 4.5/s
line_number_in_loop: 13.0/s
inc_in_loop: 15.5/s
flag_in_loop: 15.8/s
strip_before_loop: 19.9/s
Run Code Online (Sandbox Code Playgroud)
我很震惊地发现这my @array = <$fh>是一个很大的差距.考虑到perl解释器中发生的所有工作,我本以为它会是最快的.但是,它是唯一一个分配内存来容纳所有行的人,这可能是性能滞后的原因.
使用$.是另一个惊喜.也许这是访问魔术全球的成本,或者可能是它进行数字比较.
并且,正如算法分析所预测的那样,将头部校验码放在循环之外是最快的.但不是很多.可能还不足以担心你是否正在使用下两个最快的.
Gur*_*uru 20
您可以第一次为它分配一个虚拟变量:
#!/usr/bin/perl
use strict;
use warnings;
open my $fh, '<','a.txt' or die $!;
my $dummy=<$fh>; #First line is read here
while(<$fh>){
print ;
}
close($fh);
Run Code Online (Sandbox Code Playgroud)
我总是使用$.(当前行号)来实现这个目的:
#!/usr/bin/perl
use strict;
use warnings;
open my $fh, '<', 'myfile.txt' or die "$!\n";
while (<$fh>) {
next if $. < 2; # Skip first line
# Do stuff with subsequent lines
}
Run Code Online (Sandbox Code Playgroud)