Perl 变量实例化与双哈希引用访问

Perl 变量实例化与双哈希引用访问,perl,Perl,起初,我在寻找一种访问hash ref元素的快速方法(如果没有可用的值,则使用默认值) 因此,我尝试了以下方法: use strict; use warnings; use DateTime; my $hashref = { }; for (0..249) { my $lIdx = $_ * 2; $hashref->{"MYKEY$lIdx"} = "MYVAL$lIdx"; } sub WithVariable{ my $result = $hashref->{

起初,我在寻找一种访问hash ref元素的快速方法(如果没有可用的值,则使用默认值)

因此,我尝试了以下方法:

use strict;
use warnings;
use DateTime;
my $hashref = { };
for (0..249) {
  my $lIdx = $_ * 2;
  $hashref->{"MYKEY$lIdx"} = "MYVAL$lIdx";
}

sub WithVariable{
    my $result = $hashref->{"MYKEY$_[0]"};
    return defined $result ? $result : "NONE";
}

sub WithoutVariable{
    return defined $hashref->{"MYKEY$_[0]"} ? $hashref->{"MYKEY$_[0]"} : "NONE";
}
$|++;
my @preciousvalues1 = ();
my @preciousvalues2 = ();
my $dt = DateTime->now;
for (1..25000) { for (0..498) { push @preciousvalues1, WithVariable($_) } }
my $lag = DateTime->now - $dt;
print "With a variable: ", $lag->seconds, "\n";
$dt = DateTime->now;
for (1..25000) { for (0..498) { push @preciousvalues2, WithoutVariable($_) } }
$lag = DateTime->now - $dt;
print "Without a variable: ", $lag->seconds, "\n";

print "Done\n";
但是结果似乎是随机的,perl似乎在打印“完成”之后做了很多事情,并且要花很长时间才能退出

我的问题是:

  • 如果找不到值,那么允许使用默认值访问散列中存储的值的函数的整洁实现是什么
  • perl打印“完成”后到底在做什么?垃圾收集
  • Perl版本:这是Perl,v5.10.1,为MSWin32-x86-multi-thread构建

  • 从5.10版开始,您可以使用
    /
    (已定义或)运算符测试已定义的粗糙度,并在一个步骤中指定默认值

  • 在脚本的末尾。这将立即结束脚本,绕过Perl的正常关闭例程(以及放入
    end{}
    块中的任何代码)。在这个脚本上使用它可能没什么大不了的,但是通常使用
    \u exit

    不是一个最佳实践,正如我在评论中已经说过的,使用它来进行这些比较。Benchmark处理测试计时和打印报告的所有精细细节

    另一件值得一提的事情是,你的测试并不是在测试你认为它是什么。您的测试将值推送到
    @preciousvalues1
    @preciousvalues2
    上。每个测试迭代将大约500个结果添加到其中一个数组中。由于没有在迭代之间清除数组,因此最终会得到两个数组,每个数组都有大约1250万个条目。我猜这会驱使您交换,并导致您进入缓慢、半随机的执行时间。这也是退出程序延迟的原因。您已经为这些结构分配了大量RAM。Perl希望正确地分解它们,并确保触发任何析构函数或结束块

    这是一个经过清理的测试版本,重点是哈希访问。我添加了mobrule的解决方案以供比较

    use strict;
    use warnings;
    use Benchmark qw(cmpthese);
    
    
    my $hashref = { };
    for (0..249) {
      my $lIdx = $_ * 2;
      $hashref->{"MYKEY$lIdx"} = "MYVAL$lIdx";
    }
    
    sub WithVariable{
        my $result = $hashref->{"MYKEY$_[0]"};
        return defined $result ? $result : "NONE";
    }
    
    sub WithoutVariable{
        return defined $hashref->{"MYKEY$_[0]"} ? $hashref->{"MYKEY$_[0]"} : "NONE";
    }
    
    cmpthese( 25000, {
        "With Var" => sub {
            my @vals;
            push @vals, WithVariable($_) for 0..498;
        },
        "Without Var" => sub {
            my @vals;
            push @vals, WithoutVariable($_) for 0..498;
        },
        "Mobrule" => sub {
            my @vals;
            push @vals, $hashref->{"MYKEY$_"} // 'NONE' for 0..498;
        }
    } );
    
    在我的系统上显示以下结果:

                  Rate    With Var Without Var     Mobrule
    With Var    1382/s          --         -0%        -49%
    Without Var 1389/s          1%          --        -49%
    Mobrule     2700/s         95%         94%          --
    

    很明显,mobrule的解决方案速度更快,而其他两种实现之间只有很小的区别。最大的区别在于mobrule的解决方案没有执行其他两个实现所使用的函数调用。

    您确实应该使用基准模块进行此类比较。基准测试是核心的一部分,所以没有理由不使用它。您需要更改Mobrule版本以使用
    $hashref->{“MYKEY$\}
    来获得准确的基准。虽然我认为这不会改变结果。谢谢,文达苏。又一个例子说明了尝试测试一件事情是多么容易,最后又测试了另一件事情。我修复了代码并更新了结果。
    use strict;
    use warnings;
    use Benchmark qw(cmpthese);
    
    
    my $hashref = { };
    for (0..249) {
      my $lIdx = $_ * 2;
      $hashref->{"MYKEY$lIdx"} = "MYVAL$lIdx";
    }
    
    sub WithVariable{
        my $result = $hashref->{"MYKEY$_[0]"};
        return defined $result ? $result : "NONE";
    }
    
    sub WithoutVariable{
        return defined $hashref->{"MYKEY$_[0]"} ? $hashref->{"MYKEY$_[0]"} : "NONE";
    }
    
    cmpthese( 25000, {
        "With Var" => sub {
            my @vals;
            push @vals, WithVariable($_) for 0..498;
        },
        "Without Var" => sub {
            my @vals;
            push @vals, WithoutVariable($_) for 0..498;
        },
        "Mobrule" => sub {
            my @vals;
            push @vals, $hashref->{"MYKEY$_"} // 'NONE' for 0..498;
        }
    } );
    
                  Rate    With Var Without Var     Mobrule
    With Var    1382/s          --         -0%        -49%
    Without Var 1389/s          1%          --        -49%
    Mobrule     2700/s         95%         94%          --