这段代码
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秒.将调试输出行放在子程序中的"foreach"之前,并且在运行期间输出行之间有明显的延迟,大约为1秒,而对于perl主要部分中的版本,则没有可测量的延迟(因此输出线之间<0.1秒左右).
该数组通常非常小,有1或2个(99%的时间)条目,很少有12个.另一方面,散列非常非常大.它有1.5M键,每个键有6个由子键访问的值.两者都是通过引用传递的,因此它们的内容大小确实不应该重要.
什么可能导致这种延迟?我不记得在Perl子例程调用上有这么多的调用开销,并且输入参数是通过引用传递的,所以它不像是必须复制巨大的哈希.(虽然执行速度表明它可能正在这样做.)
Centos 5上的Perl 5.8.8.
这很慢,因为当你这样做
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"}
.