通过引用子例程传递大哈希的性能降低

 老黑_微笑 发布于 2022-12-31 18:29

这段代码

        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.

1 个回答
  • 这很慢,因为当你这样做

    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"}.

    2022-12-31 18:31 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有