此代码
foreach my $ti (@forward){
my $new_bs = %blast_values->{ $ti }->{"bitscore"};
if($new_bs > $fbs){
$fti = $ti;
$fbs = $new_bs;
}
}
my $fqstart = %blast_values->{ $fti }->{"qstart"};
my $fqend = %blast_values->{ $fti }->{"qend"};
my $fsstart = %blast_values->{ $fti }->{"sstart"};
my $fsend = %blast_values->{ $fti }->{"send"};
最初是通过子程序调用完成的:
my ($fti, $fqstart, $fqend, $fsstart, $fsend, $fbs) = best_one(\@forward,\%blast_values);
在子程序内部:
my @forward = @{$_[0]};
my %blast_values = %{$_[1]};
然而,子程序版本的运行速度比本文顶部显示的代码慢了约40倍。子程序版本是相同的代码,只是移入子程序然后返回指示的标量值。如果我让它运行完成,子程序将被调用大约30K次,这是我从未做过的,因为它需要大约1800秒。将调试输出行放在&#34; foreach&#34;之前。在子程序中,在运行期间输出线之间存在明显的延迟,大约为1秒,而对于perl主要部分中的版本,没有可测量的延迟(因此输出线之间<0.1秒左右) )。
数组通常非常小,有1或2个(99%的时间)条目,很少有12个。另一方面,哈希非常非常大。它有1.5M键,每个键有6个由子键访问的值。两者都是通过引用传递的,所以它们的内容大小确实不应该重要。
可能导致这种延迟的原因是什么?我不记得在Perl子程序调用上有这么多的调用开销,并且输入参数是通过引用传递的,所以它不必复制巨大的哈希。 (虽然执行速度表明它可能正在这样做。)
Centos 5上的Perl 5.8.8。
答案 0 :(得分:6)
这很慢,因为当你这样做时
my @forward = @{$_[0]};
my %blast_values = %{$_[1]};
您正在取消引用您传入的引用并将引用的结构复制到新变量中。如果%blast_values
非常大,那就是很多工作。
相反,只需使用引用而不复制。 (这就是他们的目的。)
my $forward = shift;
my $blast_values = shift;
my $fqstart = $blast_values->{ $fti }->{"qstart"};
# etc
另外,我假设你知道%blast_values->{ $fti }->{"qstart"}
没有意义。它完全有效的事实是由于Perl中的一个错误。使用这样的构造已经发出警告(“使用哈希作为参考被弃用”)多年。您应该使用$blast_values{ $fti }->{"qstart"}
。